@mathers101/react-native-render-rich-text 0.0.0-stage → 0.1.9

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (358) hide show
  1. package/LICENSE +20 -0
  2. package/README.md +140 -3
  3. package/ReactNativeRenderRichText.podspec +23 -0
  4. package/android/build.gradle +86 -0
  5. package/android/consumer-rules.pro +3 -0
  6. package/android/src/main/AndroidManifest.xml +2 -0
  7. package/android/src/main/cpp/jni-adapter.cpp +191 -0
  8. package/android/src/main/java/com/renderrichtext/EnrichedTiptapText.kt +673 -0
  9. package/android/src/main/java/com/renderrichtext/EnrichedTiptapTextLayoutManager.kt +24 -0
  10. package/android/src/main/java/com/renderrichtext/EnrichedTiptapTextManager.kt +405 -0
  11. package/android/src/main/java/com/renderrichtext/EnrichedTiptapTextPackage.kt +13 -0
  12. package/android/src/main/java/com/renderrichtext/MeasurementStore.kt +644 -0
  13. package/android/src/main/java/com/renderrichtext/accessibility/AccessibilityLabels.kt +17 -0
  14. package/android/src/main/java/com/renderrichtext/accessibility/AccessibleTiptapTextView.kt +112 -0
  15. package/android/src/main/java/com/renderrichtext/accessibility/TiptapAccessibilityHelper.kt +576 -0
  16. package/android/src/main/java/com/renderrichtext/events/CodeBlockPressEvent.kt +24 -0
  17. package/android/src/main/java/com/renderrichtext/events/ContextMenuItemPressEvent.kt +28 -0
  18. package/android/src/main/java/com/renderrichtext/events/CopyPressEvent.kt +24 -0
  19. package/android/src/main/java/com/renderrichtext/events/FactoidPressEvent.kt +23 -0
  20. package/android/src/main/java/com/renderrichtext/events/ImagePressEvent.kt +25 -0
  21. package/android/src/main/java/com/renderrichtext/events/LatexErrorEvent.kt +29 -0
  22. package/android/src/main/java/com/renderrichtext/events/LinkLongPressEvent.kt +23 -0
  23. package/android/src/main/java/com/renderrichtext/events/LinkPressEvent.kt +23 -0
  24. package/android/src/main/java/com/renderrichtext/events/MentionLongPressEvent.kt +25 -0
  25. package/android/src/main/java/com/renderrichtext/events/MentionPressEvent.kt +25 -0
  26. package/android/src/main/java/com/renderrichtext/events/TaskListItemPressEvent.kt +26 -0
  27. package/android/src/main/java/com/renderrichtext/math/LatexErrorReporter.kt +9 -0
  28. package/android/src/main/java/com/renderrichtext/parser/Parser.kt +59 -0
  29. package/android/src/main/java/com/renderrichtext/parser/TextLinkMatching.kt +35 -0
  30. package/android/src/main/java/com/renderrichtext/parser/TiptapASTNode.kt +69 -0
  31. package/android/src/main/java/com/renderrichtext/renderer/BaselineShiftRenderer.kt +45 -0
  32. package/android/src/main/java/com/renderrichtext/renderer/BlankLineRenderer.kt +39 -0
  33. package/android/src/main/java/com/renderrichtext/renderer/BlockStyleContext.kt +181 -0
  34. package/android/src/main/java/com/renderrichtext/renderer/BlockquoteRenderer.kt +243 -0
  35. package/android/src/main/java/com/renderrichtext/renderer/BlockquoteTextRenderer.kt +56 -0
  36. package/android/src/main/java/com/renderrichtext/renderer/CodeBlockRenderer.kt +135 -0
  37. package/android/src/main/java/com/renderrichtext/renderer/CodeRenderer.kt +37 -0
  38. package/android/src/main/java/com/renderrichtext/renderer/EmphasisRenderer.kt +28 -0
  39. package/android/src/main/java/com/renderrichtext/renderer/FactoidRenderer.kt +97 -0
  40. package/android/src/main/java/com/renderrichtext/renderer/HeadingRenderer.kt +81 -0
  41. package/android/src/main/java/com/renderrichtext/renderer/HighlightRenderer.kt +26 -0
  42. package/android/src/main/java/com/renderrichtext/renderer/LineBreakRenderer.kt +17 -0
  43. package/android/src/main/java/com/renderrichtext/renderer/LinkRenderer.kt +90 -0
  44. package/android/src/main/java/com/renderrichtext/renderer/ListContextManager.kt +109 -0
  45. package/android/src/main/java/com/renderrichtext/renderer/ListItemRenderer.kt +211 -0
  46. package/android/src/main/java/com/renderrichtext/renderer/ListRenderer.kt +133 -0
  47. package/android/src/main/java/com/renderrichtext/renderer/MentionRenderer.kt +85 -0
  48. package/android/src/main/java/com/renderrichtext/renderer/NodeRenderer.kt +207 -0
  49. package/android/src/main/java/com/renderrichtext/renderer/ParagraphRenderer.kt +91 -0
  50. package/android/src/main/java/com/renderrichtext/renderer/Renderer.kt +148 -0
  51. package/android/src/main/java/com/renderrichtext/renderer/SoftBreakRenderer.kt +17 -0
  52. package/android/src/main/java/com/renderrichtext/renderer/SpanStyleCache.kt +143 -0
  53. package/android/src/main/java/com/renderrichtext/renderer/StrikethroughRenderer.kt +28 -0
  54. package/android/src/main/java/com/renderrichtext/renderer/StrongRenderer.kt +28 -0
  55. package/android/src/main/java/com/renderrichtext/renderer/TextRenderer.kt +31 -0
  56. package/android/src/main/java/com/renderrichtext/renderer/ThematicBreakRenderer.kt +46 -0
  57. package/android/src/main/java/com/renderrichtext/renderer/UnderlineRenderer.kt +28 -0
  58. package/android/src/main/java/com/renderrichtext/spans/BaseListSpan.kt +164 -0
  59. package/android/src/main/java/com/renderrichtext/spans/BaselineShiftSpan.kt +27 -0
  60. package/android/src/main/java/com/renderrichtext/spans/BlockquoteSpan.kt +302 -0
  61. package/android/src/main/java/com/renderrichtext/spans/CodeBackgroundSpan.kt +205 -0
  62. package/android/src/main/java/com/renderrichtext/spans/CodeBlockSpan.kt +216 -0
  63. package/android/src/main/java/com/renderrichtext/spans/CodeSpan.kt +32 -0
  64. package/android/src/main/java/com/renderrichtext/spans/EmphasisSpan.kt +42 -0
  65. package/android/src/main/java/com/renderrichtext/spans/FactoidBackgroundSpan.kt +265 -0
  66. package/android/src/main/java/com/renderrichtext/spans/FactoidPaddingSpan.kt +258 -0
  67. package/android/src/main/java/com/renderrichtext/spans/FactoidSpan.kt +32 -0
  68. package/android/src/main/java/com/renderrichtext/spans/FadeInSpan.kt +29 -0
  69. package/android/src/main/java/com/renderrichtext/spans/HeadingSpan.kt +38 -0
  70. package/android/src/main/java/com/renderrichtext/spans/HighlightSpan.kt +80 -0
  71. package/android/src/main/java/com/renderrichtext/spans/ImageSpan.kt +481 -0
  72. package/android/src/main/java/com/renderrichtext/spans/InlineBackgroundGeometry.kt +42 -0
  73. package/android/src/main/java/com/renderrichtext/spans/LineHeightSpan.kt +39 -0
  74. package/android/src/main/java/com/renderrichtext/spans/LinkPillIconCache.kt +154 -0
  75. package/android/src/main/java/com/renderrichtext/spans/LinkPillSpan.kt +381 -0
  76. package/android/src/main/java/com/renderrichtext/spans/LinkSpan.kt +68 -0
  77. package/android/src/main/java/com/renderrichtext/spans/ListItemSpacingSpan.kt +33 -0
  78. package/android/src/main/java/com/renderrichtext/spans/ListMarkerAnchorSpan.kt +38 -0
  79. package/android/src/main/java/com/renderrichtext/spans/MarginBottomSpan.kt +76 -0
  80. package/android/src/main/java/com/renderrichtext/spans/MentionChipSpan.kt +132 -0
  81. package/android/src/main/java/com/renderrichtext/spans/MentionSpan.kt +46 -0
  82. package/android/src/main/java/com/renderrichtext/spans/OrderedListSpan.kt +127 -0
  83. package/android/src/main/java/com/renderrichtext/spans/SpoilerSpan.kt +33 -0
  84. package/android/src/main/java/com/renderrichtext/spans/StrikethroughSpan.kt +12 -0
  85. package/android/src/main/java/com/renderrichtext/spans/StrongSpan.kt +39 -0
  86. package/android/src/main/java/com/renderrichtext/spans/TaskListSpan.kt +143 -0
  87. package/android/src/main/java/com/renderrichtext/spans/TextSpan.kt +26 -0
  88. package/android/src/main/java/com/renderrichtext/spans/ThematicBreakSpan.kt +69 -0
  89. package/android/src/main/java/com/renderrichtext/spans/UnorderedListSpan.kt +96 -0
  90. package/android/src/main/java/com/renderrichtext/spoiler/SpoilerStubs.kt +46 -0
  91. package/android/src/main/java/com/renderrichtext/styles/BaseBlockStyle.kt +11 -0
  92. package/android/src/main/java/com/renderrichtext/styles/BlockquoteStyle.kt +83 -0
  93. package/android/src/main/java/com/renderrichtext/styles/CodeBlockStyle.kt +80 -0
  94. package/android/src/main/java/com/renderrichtext/styles/CodeStyle.kt +26 -0
  95. package/android/src/main/java/com/renderrichtext/styles/EmphasisStyle.kt +21 -0
  96. package/android/src/main/java/com/renderrichtext/styles/FactoidStyle.kt +21 -0
  97. package/android/src/main/java/com/renderrichtext/styles/HeadingStyle.kt +33 -0
  98. package/android/src/main/java/com/renderrichtext/styles/HighlightStyle.kt +19 -0
  99. package/android/src/main/java/com/renderrichtext/styles/ImageStyle.kt +29 -0
  100. package/android/src/main/java/com/renderrichtext/styles/InlineImageStyle.kt +17 -0
  101. package/android/src/main/java/com/renderrichtext/styles/InlineMathStyle.kt +17 -0
  102. package/android/src/main/java/com/renderrichtext/styles/LinkPillContent.kt +36 -0
  103. package/android/src/main/java/com/renderrichtext/styles/LinkPillStyle.kt +44 -0
  104. package/android/src/main/java/com/renderrichtext/styles/LinkStyle.kt +23 -0
  105. package/android/src/main/java/com/renderrichtext/styles/LinkVariantEntry.kt +34 -0
  106. package/android/src/main/java/com/renderrichtext/styles/ListStyle.kt +65 -0
  107. package/android/src/main/java/com/renderrichtext/styles/MathStyle.kt +29 -0
  108. package/android/src/main/java/com/renderrichtext/styles/MentionStyle.kt +19 -0
  109. package/android/src/main/java/com/renderrichtext/styles/ParagraphStyle.kt +33 -0
  110. package/android/src/main/java/com/renderrichtext/styles/SpoilerStyle.kt +27 -0
  111. package/android/src/main/java/com/renderrichtext/styles/StrikethroughStyle.kt +17 -0
  112. package/android/src/main/java/com/renderrichtext/styles/StrongStyle.kt +21 -0
  113. package/android/src/main/java/com/renderrichtext/styles/StyleConfig.kt +411 -0
  114. package/android/src/main/java/com/renderrichtext/styles/StyleParser.kt +92 -0
  115. package/android/src/main/java/com/renderrichtext/styles/SubscriptStyle.kt +16 -0
  116. package/android/src/main/java/com/renderrichtext/styles/SuperscriptStyle.kt +16 -0
  117. package/android/src/main/java/com/renderrichtext/styles/TableStyle.kt +75 -0
  118. package/android/src/main/java/com/renderrichtext/styles/TaskListStyle.kt +29 -0
  119. package/android/src/main/java/com/renderrichtext/styles/TextAlignment.kt +32 -0
  120. package/android/src/main/java/com/renderrichtext/styles/ThematicBreakStyle.kt +23 -0
  121. package/android/src/main/java/com/renderrichtext/styles/UnderlineStyle.kt +17 -0
  122. package/android/src/main/java/com/renderrichtext/styles/VideoStyle.kt +31 -0
  123. package/android/src/main/java/com/renderrichtext/utils/common/BorderStyleUtils.kt +86 -0
  124. package/android/src/main/java/com/renderrichtext/utils/common/BreakStrategyUtils.kt +32 -0
  125. package/android/src/main/java/com/renderrichtext/utils/common/CodeBlockHighlighter.kt +36 -0
  126. package/android/src/main/java/com/renderrichtext/utils/common/CodeBlockNode.kt +42 -0
  127. package/android/src/main/java/com/renderrichtext/utils/common/EllipsizeUtils.kt +27 -0
  128. package/android/src/main/java/com/renderrichtext/utils/common/EnrichedTiptapAncestorUtils.kt +10 -0
  129. package/android/src/main/java/com/renderrichtext/utils/common/FeatureFlags.kt +9 -0
  130. package/android/src/main/java/com/renderrichtext/utils/common/LinkRecognitionProps.kt +31 -0
  131. package/android/src/main/java/com/renderrichtext/utils/common/LinkRegexConfig.kt +56 -0
  132. package/android/src/main/java/com/renderrichtext/utils/common/MotionPreferences.kt +18 -0
  133. package/android/src/main/java/com/renderrichtext/utils/common/ReadableMapExtensions.kt +28 -0
  134. package/android/src/main/java/com/renderrichtext/utils/common/TiptapViewManagerUtils.kt +242 -0
  135. package/android/src/main/java/com/renderrichtext/utils/common/layout/RTLUtils.kt +6 -0
  136. package/android/src/main/java/com/renderrichtext/utils/common/serialization/TiptapASTSerializer.kt +368 -0
  137. package/android/src/main/java/com/renderrichtext/utils/text/ImageCache.kt +88 -0
  138. package/android/src/main/java/com/renderrichtext/utils/text/ImageDownloader.kt +203 -0
  139. package/android/src/main/java/com/renderrichtext/utils/text/LocalImageLoader.kt +167 -0
  140. package/android/src/main/java/com/renderrichtext/utils/text/TailFadeInAnimator.kt +84 -0
  141. package/android/src/main/java/com/renderrichtext/utils/text/conversion/HTMLGenerator.kt +1105 -0
  142. package/android/src/main/java/com/renderrichtext/utils/text/conversion/TiptapExtractor.kt +423 -0
  143. package/android/src/main/java/com/renderrichtext/utils/text/extensions/ParagraphUtils.kt +9 -0
  144. package/android/src/main/java/com/renderrichtext/utils/text/extensions/SpannableExtensions.kt +9 -0
  145. package/android/src/main/java/com/renderrichtext/utils/text/extensions/TextPaintExtensions.kt +76 -0
  146. package/android/src/main/java/com/renderrichtext/utils/text/interaction/CheckboxTouchHelper.kt +61 -0
  147. package/android/src/main/java/com/renderrichtext/utils/text/interaction/TaskListTapUtils.kt +286 -0
  148. package/android/src/main/java/com/renderrichtext/utils/text/span/ApplyLineHeight.kt +39 -0
  149. package/android/src/main/java/com/renderrichtext/utils/text/span/BlockSpacing.kt +142 -0
  150. package/android/src/main/java/com/renderrichtext/utils/text/span/SpanFlags.kt +43 -0
  151. package/android/src/main/java/com/renderrichtext/utils/text/span/WidthAwareSpans.kt +30 -0
  152. package/android/src/main/java/com/renderrichtext/utils/text/view/CodeBlockPressHost.kt +15 -0
  153. package/android/src/main/java/com/renderrichtext/utils/text/view/ImagePressHost.kt +19 -0
  154. package/android/src/main/java/com/renderrichtext/utils/text/view/LinkEvents.kt +88 -0
  155. package/android/src/main/java/com/renderrichtext/utils/text/view/LinkLongPressMovementMethod.kt +449 -0
  156. package/android/src/main/java/com/renderrichtext/utils/text/view/SelectionActionMode.kt +235 -0
  157. package/android/src/main/java/com/renderrichtext/utils/text/view/TextSelectionColors.kt +48 -0
  158. package/android/src/main/java/com/renderrichtext/utils/text/view/TextViewSetup.kt +119 -0
  159. package/android/src/main/java/com/renderrichtext/views/ContextMenuPopup.kt +217 -0
  160. package/android/src/main/java/com/renderrichtext/views/CopyGlyph.kt +101 -0
  161. package/android/src/main/java/com/renderrichtext/views/WrapGlyph.kt +40 -0
  162. package/android/src/main/jni/CMakeLists.txt +52 -0
  163. package/android/src/main/jni/react/renderer/components/RichTextSpec/ComponentDescriptors.h +30 -0
  164. package/android/src/main/jni/react/renderer/components/RichTextSpec/TiptapTextComponentDescriptor.h +29 -0
  165. package/android/src/main/jni/react/renderer/components/RichTextSpec/TiptapTextMeasurementManager.cpp +45 -0
  166. package/android/src/main/jni/react/renderer/components/RichTextSpec/TiptapTextMeasurementManager.h +21 -0
  167. package/android/src/main/jni/react/renderer/components/RichTextSpec/TiptapTextShadowNode.cpp +38 -0
  168. package/android/src/main/jni/react/renderer/components/RichTextSpec/TiptapTextShadowNode.h +53 -0
  169. package/android/src/main/jni/react/renderer/components/RichTextSpec/TiptapTextState.cpp +9 -0
  170. package/android/src/main/jni/react/renderer/components/RichTextSpec/TiptapTextState.h +24 -0
  171. package/android/src/main/jni/react/renderer/components/RichTextSpec/conversions.h +40 -0
  172. package/cpp/parser/TiptapASTNode.hpp +68 -0
  173. package/cpp/parser/TiptapParser.cpp +233 -0
  174. package/cpp/parser/TiptapParser.hpp +13 -0
  175. package/cpp/vendor/nlohmann/json.hpp +24765 -0
  176. package/ios/EnrichedTiptapText.h +27 -0
  177. package/ios/EnrichedTiptapText.mm +1222 -0
  178. package/ios/attachments/ENRMImageAttachment.h +51 -0
  179. package/ios/attachments/ENRMImageAttachment.m +398 -0
  180. package/ios/attachments/ENRMLinkPillAttachment.h +47 -0
  181. package/ios/attachments/ENRMLinkPillAttachment.m +324 -0
  182. package/ios/attachments/ENRMLinkPillIconCache.h +28 -0
  183. package/ios/attachments/ENRMLinkPillIconCache.m +181 -0
  184. package/ios/attachments/ENRMLinkPillText.h +27 -0
  185. package/ios/attachments/ENRMLinkPillText.m +118 -0
  186. package/ios/attachments/ENRMMathInlineAttachment.h +7 -0
  187. package/ios/attachments/ENRMMathInlineAttachment.m +4 -0
  188. package/ios/attachments/ThematicBreakAttachment.h +15 -0
  189. package/ios/attachments/ThematicBreakAttachment.m +33 -0
  190. package/ios/internals/ENRMViewFreeMeasurement.h +208 -0
  191. package/ios/internals/EnrichedTiptapTextComponentDescriptor.h +19 -0
  192. package/ios/internals/EnrichedTiptapTextShadowNode.h +43 -0
  193. package/ios/internals/EnrichedTiptapTextShadowNode.mm +69 -0
  194. package/ios/internals/EnrichedTiptapTextState.h +24 -0
  195. package/ios/internals/MeasurementCache.h +308 -0
  196. package/ios/internals/ShadowMeasurementUtils.h +145 -0
  197. package/ios/parser/ENRMTextLinkAttributes.h +7 -0
  198. package/ios/parser/ENRMTiptapParser.h +33 -0
  199. package/ios/parser/ENRMTiptapParser.mm +73 -0
  200. package/ios/parser/TiptapASTNode.h +57 -0
  201. package/ios/parser/TiptapASTNode.m +52 -0
  202. package/ios/parser/TiptapParserBridge.mm +179 -0
  203. package/ios/renderer/AttributedRenderer.h +23 -0
  204. package/ios/renderer/AttributedRenderer.m +229 -0
  205. package/ios/renderer/BaseRenderer.h +33 -0
  206. package/ios/renderer/BaseRenderer.m +46 -0
  207. package/ios/renderer/BaselineShiftTextAttributes.h +10 -0
  208. package/ios/renderer/BaselineShiftTextAttributes.m +26 -0
  209. package/ios/renderer/BlankLineRenderer.h +4 -0
  210. package/ios/renderer/BlankLineRenderer.m +51 -0
  211. package/ios/renderer/BlockquoteRenderer.h +6 -0
  212. package/ios/renderer/BlockquoteRenderer.m +258 -0
  213. package/ios/renderer/CodeBlockRenderer.h +9 -0
  214. package/ios/renderer/CodeBlockRenderer.m +99 -0
  215. package/ios/renderer/CodeRenderer.h +9 -0
  216. package/ios/renderer/CodeRenderer.m +69 -0
  217. package/ios/renderer/ENRMBlockquoteTextRenderer.h +25 -0
  218. package/ios/renderer/ENRMBlockquoteTextRenderer.m +48 -0
  219. package/ios/renderer/EmphasisRenderer.h +5 -0
  220. package/ios/renderer/EmphasisRenderer.m +100 -0
  221. package/ios/renderer/FactoidRenderer.h +9 -0
  222. package/ios/renderer/FactoidRenderer.m +130 -0
  223. package/ios/renderer/HeadingRenderer.h +6 -0
  224. package/ios/renderer/HeadingRenderer.m +103 -0
  225. package/ios/renderer/HighlightRenderer.h +7 -0
  226. package/ios/renderer/HighlightRenderer.m +33 -0
  227. package/ios/renderer/LinkRenderer.h +6 -0
  228. package/ios/renderer/LinkRenderer.m +158 -0
  229. package/ios/renderer/ListItemRenderer.h +24 -0
  230. package/ios/renderer/ListItemRenderer.m +283 -0
  231. package/ios/renderer/ListRenderer.h +13 -0
  232. package/ios/renderer/ListRenderer.m +126 -0
  233. package/ios/renderer/MentionRenderer.h +9 -0
  234. package/ios/renderer/MentionRenderer.m +96 -0
  235. package/ios/renderer/NodeRenderer.h +8 -0
  236. package/ios/renderer/ParagraphRenderer.h +6 -0
  237. package/ios/renderer/ParagraphRenderer.m +85 -0
  238. package/ios/renderer/RenderContext.h +145 -0
  239. package/ios/renderer/RenderContext.m +403 -0
  240. package/ios/renderer/RendererFactory.h +12 -0
  241. package/ios/renderer/RendererFactory.m +158 -0
  242. package/ios/renderer/StrikethroughRenderer.h +5 -0
  243. package/ios/renderer/StrikethroughRenderer.m +30 -0
  244. package/ios/renderer/StrongRenderer.h +5 -0
  245. package/ios/renderer/StrongRenderer.m +88 -0
  246. package/ios/renderer/TextRenderer.h +6 -0
  247. package/ios/renderer/TextRenderer.m +18 -0
  248. package/ios/renderer/ThematicBreakRenderer.h +4 -0
  249. package/ios/renderer/ThematicBreakRenderer.m +42 -0
  250. package/ios/renderer/UnderlineRenderer.h +4 -0
  251. package/ios/renderer/UnderlineRenderer.m +41 -0
  252. package/ios/styles/ENRMFontSlot.h +12 -0
  253. package/ios/styles/ENRMFontSlot.m +24 -0
  254. package/ios/styles/StyleConfig.h +488 -0
  255. package/ios/styles/StyleConfig.mm +2820 -0
  256. package/ios/utils/AccessibilityInfo.h +35 -0
  257. package/ios/utils/AccessibilityInfo.m +24 -0
  258. package/ios/utils/BlockquoteBorder.h +26 -0
  259. package/ios/utils/BlockquoteBorder.m +294 -0
  260. package/ios/utils/CodeBackground.h +19 -0
  261. package/ios/utils/CodeBackground.m +197 -0
  262. package/ios/utils/CodeBlockBackground.h +17 -0
  263. package/ios/utils/CodeBlockBackground.m +103 -0
  264. package/ios/utils/ContextMenuUtils.h +76 -0
  265. package/ios/utils/ContextMenuUtils.mm +75 -0
  266. package/ios/utils/ENRMAccessibilityLabels.h +40 -0
  267. package/ios/utils/ENRMAccessibilityLabels.m +5 -0
  268. package/ios/utils/ENRMAsyncRenderCoordinator.h +24 -0
  269. package/ios/utils/ENRMAsyncRenderCoordinator.m +37 -0
  270. package/ios/utils/ENRMAtomicSize.h +65 -0
  271. package/ios/utils/ENRMCodeBlockContent.h +37 -0
  272. package/ios/utils/ENRMCodeBlockContent.mm +89 -0
  273. package/ios/utils/ENRMFeatureFlags.h +25 -0
  274. package/ios/utils/ENRMImageDownloader.h +30 -0
  275. package/ios/utils/ENRMImageDownloader.m +168 -0
  276. package/ios/utils/ENRMLatexErrorCoordinator.h +27 -0
  277. package/ios/utils/ENRMLatexErrorCoordinator.mm +75 -0
  278. package/ios/utils/ENRMLatexErrorReporting.h +13 -0
  279. package/ios/utils/ENRMLinkContextMenus.h +93 -0
  280. package/ios/utils/ENRMLinkContextMenus.m +178 -0
  281. package/ios/utils/ENRMLinkRegexConfig.h +30 -0
  282. package/ios/utils/ENRMLinkRegexConfig.mm +104 -0
  283. package/ios/utils/ENRMLinkRegexProps.h +23 -0
  284. package/ios/utils/ENRMLocalImageLoader.h +35 -0
  285. package/ios/utils/ENRMLocalImageLoader.m +111 -0
  286. package/ios/utils/ENRMMenuAction.h +27 -0
  287. package/ios/utils/ENRMMenuAction.m +33 -0
  288. package/ios/utils/ENRMSpoilerOverlayManager.h +15 -0
  289. package/ios/utils/ENRMSpoilerOverlayManager.m +19 -0
  290. package/ios/utils/ENRMSpoilerTapUtils.h +6 -0
  291. package/ios/utils/ENRMSpoilerTapUtils.m +11 -0
  292. package/ios/utils/ENRMTailFadeInAnimator.h +16 -0
  293. package/ios/utils/ENRMTailFadeInAnimator.m +161 -0
  294. package/ios/utils/ENRMTextHitTest.h +23 -0
  295. package/ios/utils/ENRMTextHitTest.m +20 -0
  296. package/ios/utils/ENRMTextInteractionUtils.h +20 -0
  297. package/ios/utils/ENRMTextInteractionUtils.m +15 -0
  298. package/ios/utils/ENRMTextRenderer.h +38 -0
  299. package/ios/utils/ENRMTextRenderer.m +54 -0
  300. package/ios/utils/ENRMTextViewSetup.h +132 -0
  301. package/ios/utils/ENRMUIKit.h +429 -0
  302. package/ios/utils/EditMenuUtils.h +105 -0
  303. package/ios/utils/EditMenuUtils.m +143 -0
  304. package/ios/utils/FactoidBackground.h +20 -0
  305. package/ios/utils/FactoidBackground.m +161 -0
  306. package/ios/utils/FontScaleObserver.h +10 -0
  307. package/ios/utils/FontScaleObserver.m +55 -0
  308. package/ios/utils/FontUtils.h +31 -0
  309. package/ios/utils/FontUtils.m +63 -0
  310. package/ios/utils/HTMLGenerator.h +25 -0
  311. package/ios/utils/HTMLGenerator.m +1041 -0
  312. package/ios/utils/HeightUpdateUtils.h +25 -0
  313. package/ios/utils/ImageRequestHeaderUtils.h +35 -0
  314. package/ios/utils/LastElementUtils.h +97 -0
  315. package/ios/utils/LinkContextMenuUtils.h +55 -0
  316. package/ios/utils/LinkPillContentUtils.h +46 -0
  317. package/ios/utils/LinkTapUtils.h +56 -0
  318. package/ios/utils/LinkTapUtils.m +139 -0
  319. package/ios/utils/ListMarkerDrawer.h +15 -0
  320. package/ios/utils/ListMarkerDrawer.m +239 -0
  321. package/ios/utils/MentionBackground.h +26 -0
  322. package/ios/utils/MentionBackground.m +86 -0
  323. package/ios/utils/ParagraphStyleUtils.h +87 -0
  324. package/ios/utils/ParagraphStyleUtils.m +484 -0
  325. package/ios/utils/PasteboardUtils.h +48 -0
  326. package/ios/utils/PasteboardUtils.m +166 -0
  327. package/ios/utils/RTFExportUtils.h +24 -0
  328. package/ios/utils/RTFExportUtils.m +299 -0
  329. package/ios/utils/RuntimeKeys.h +44 -0
  330. package/ios/utils/RuntimeKeys.m +13 -0
  331. package/ios/utils/SelectionColorUtils.h +14 -0
  332. package/ios/utils/StylePropsUtils.h +1340 -0
  333. package/ios/utils/TaskListTapUtils.h +6 -0
  334. package/ios/utils/TaskListTapUtils.m +14 -0
  335. package/ios/utils/TextViewLayoutManager.h +14 -0
  336. package/ios/utils/TextViewLayoutManager.mm +198 -0
  337. package/ios/utils/TiptapAccessibilityElementBuilder.h +43 -0
  338. package/ios/utils/TiptapAccessibilityElementBuilder.m +432 -0
  339. package/ios/utils/TiptapExtractor.h +17 -0
  340. package/ios/utils/TiptapExtractor.m +367 -0
  341. package/ios/views/ENRMTiptapTextView.h +25 -0
  342. package/ios/views/ENRMTiptapTextView.m +247 -0
  343. package/package.json +70 -6
  344. package/react-native.config.js +10 -0
  345. package/src/EnrichedTiptapTextNativeComponent.ts +739 -0
  346. package/src/RichText.tsx +164 -0
  347. package/src/admonitionDefaults.ts +58 -0
  348. package/src/darkModeTextStyle.ts +99 -0
  349. package/src/headingDefaults.ts +21 -0
  350. package/src/index.tsx +4 -0
  351. package/src/linkVariantUtils.ts +120 -0
  352. package/src/normalizeTiptapStyle.ts +397 -0
  353. package/src/rn-globals.d.ts +1 -0
  354. package/src/styleUtils.ts +107 -0
  355. package/src/types/TiptapStyle.ts +532 -0
  356. package/src/types/TiptapStyleInternal.ts +299 -0
  357. package/src/types/linkPill.ts +9 -0
  358. package/src/utils/isDev.ts +4 -0
@@ -0,0 +1,35 @@
1
+ #import <Foundation/Foundation.h>
2
+
3
+ @class RenderContext;
4
+
5
+ NS_ASSUME_NONNULL_BEGIN
6
+
7
+ /**
8
+ * Container for accessibility-related data extracted from RenderContext.
9
+ * Used by TiptapAccessibilityElementBuilder to build VoiceOver elements.
10
+ */
11
+ @interface AccessibilityInfo : NSObject
12
+
13
+ // Headings
14
+ @property (nonatomic, copy, readonly) NSArray<NSValue *> *headingRanges;
15
+ @property (nonatomic, copy, readonly) NSArray<NSNumber *> *headingLevels;
16
+
17
+ // Links
18
+ @property (nonatomic, copy, readonly) NSArray<NSValue *> *linkRanges;
19
+ @property (nonatomic, copy, readonly) NSArray<NSString *> *linkURLs;
20
+
21
+ // Images
22
+ @property (nonatomic, copy, readonly) NSArray<NSValue *> *imageRanges;
23
+ @property (nonatomic, copy, readonly) NSArray<NSString *> *imageAltTexts;
24
+
25
+ // List items
26
+ @property (nonatomic, copy, readonly) NSArray<NSValue *> *listItemRanges;
27
+ @property (nonatomic, copy, readonly) NSArray<NSNumber *> *listItemPositions;
28
+ @property (nonatomic, copy, readonly) NSArray<NSNumber *> *listItemDepths;
29
+ @property (nonatomic, copy, readonly) NSArray<NSNumber *> *listItemOrdered; // YES = ordered, NO = bullet
30
+
31
+ + (instancetype)infoFromContext:(RenderContext *)context;
32
+
33
+ @end
34
+
35
+ NS_ASSUME_NONNULL_END
@@ -0,0 +1,24 @@
1
+ #import "AccessibilityInfo.h"
2
+ #import "RenderContext.h"
3
+
4
+ @implementation AccessibilityInfo
5
+
6
+ + (instancetype)infoFromContext:(RenderContext *)context
7
+ {
8
+ AccessibilityInfo *info = [[AccessibilityInfo alloc] init];
9
+ if (info) {
10
+ info->_headingRanges = [context.headingRanges copy];
11
+ info->_headingLevels = [context.headingLevels copy];
12
+ info->_linkRanges = [context.linkRanges copy];
13
+ info->_linkURLs = [context.linkURLs copy];
14
+ info->_imageRanges = [context.imageRanges copy];
15
+ info->_imageAltTexts = [context.imageAltTexts copy];
16
+ info->_listItemRanges = [context.listItemRanges copy];
17
+ info->_listItemPositions = [context.listItemPositions copy];
18
+ info->_listItemDepths = [context.listItemDepths copy];
19
+ info->_listItemOrdered = [context.listItemOrdered copy];
20
+ }
21
+ return info;
22
+ }
23
+
24
+ @end
@@ -0,0 +1,26 @@
1
+ #pragma once
2
+ #import "ENRMUIKit.h"
3
+ #import "StyleConfig.h"
4
+
5
+ NS_ASSUME_NONNULL_BEGIN
6
+
7
+ extern NSString *const BlockquoteDepthAttributeName;
8
+ extern NSString *const BlockquoteBackgroundColorAttributeName;
9
+ extern NSString *const BlockquoteSpacerAttributeName;
10
+
11
+ static inline CGFloat blockquoteIndentForDepth(NSInteger depth, CGFloat levelSpacing)
12
+ {
13
+ return depth * levelSpacing;
14
+ }
15
+
16
+ @interface BlockquoteBorder : NSObject
17
+
18
+ - (instancetype)initWithConfig:(StyleConfig *)config;
19
+ - (void)drawBordersForGlyphRange:(NSRange)glyphsToShow
20
+ layoutManager:(NSLayoutManager *)layoutManager
21
+ textContainer:(NSTextContainer *)textContainer
22
+ atPoint:(CGPoint)origin;
23
+
24
+ @end
25
+
26
+ NS_ASSUME_NONNULL_END
@@ -0,0 +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
@@ -0,0 +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
@@ -0,0 +1,197 @@
1
+ #import "CodeBackground.h"
2
+ #import "ENRMUIKit.h"
3
+ #import "RenderContext.h"
4
+
5
+ NSString *const CodeAttributeName = @"Code";
6
+
7
+ static const CGFloat kCodeBackgroundCornerRadius = 2.0;
8
+ static const CGFloat kCodeBackgroundBorderWidth = 0.5;
9
+
10
+ @implementation CodeBackground {
11
+ StyleConfig *_config;
12
+ }
13
+
14
+ - (instancetype)initWithConfig:(StyleConfig *)config
15
+ {
16
+ self = [super init];
17
+ if (self) {
18
+ _config = config;
19
+ }
20
+ return self;
21
+ }
22
+
23
+ - (void)drawBackgroundsForGlyphRange:(NSRange)glyphsToShow
24
+ layoutManager:(NSLayoutManager *)layoutManager
25
+ textContainer:(NSTextContainer *)textContainer
26
+ atPoint:(CGPoint)origin
27
+ {
28
+ RCTUIColor *backgroundColor = _config.codeBackgroundColor;
29
+ if (!backgroundColor)
30
+ return;
31
+
32
+ NSTextStorage *textStorage = layoutManager.textStorage;
33
+ NSRange charRange = [layoutManager characterRangeForGlyphRange:glyphsToShow actualGlyphRange:NULL];
34
+ if (charRange.location == NSNotFound || charRange.length == 0)
35
+ return;
36
+
37
+ [textStorage enumerateAttribute:CodeAttributeName
38
+ inRange:NSMakeRange(0, textStorage.length)
39
+ options:0
40
+ usingBlock:^(id value, NSRange range, BOOL *stop) {
41
+ if (!value || range.length == 0)
42
+ return;
43
+ if (NSIntersectionRange(range, charRange).length == 0)
44
+ return;
45
+
46
+ [self drawCodeBackgroundForRange:range
47
+ layoutManager:layoutManager
48
+ textContainer:textContainer
49
+ atPoint:origin
50
+ backgroundColor:backgroundColor
51
+ borderColor:self->_config.codeBorderColor];
52
+ }];
53
+ }
54
+
55
+ - (void)drawCodeBackgroundForRange:(NSRange)range
56
+ layoutManager:(NSLayoutManager *)layoutManager
57
+ textContainer:(NSTextContainer *)textContainer
58
+ atPoint:(CGPoint)origin
59
+ backgroundColor:(RCTUIColor *)backgroundColor
60
+ borderColor:(RCTUIColor *)borderColor
61
+ {
62
+ NSRange glyphRange = [layoutManager glyphRangeForCharacterRange:range actualCharacterRange:NULL];
63
+ if (glyphRange.location == NSNotFound || glyphRange.length == 0)
64
+ return;
65
+
66
+ CGFloat referenceHeight = [self findReferenceHeightForRange:range textStorage:layoutManager.textStorage];
67
+
68
+ [layoutManager
69
+ enumerateLineFragmentsForGlyphRange:glyphRange
70
+ usingBlock:^(CGRect rect, CGRect usedRect, NSTextContainer *tc, NSRange lineRange,
71
+ BOOL *stop) {
72
+ NSRange intersect = NSIntersectionRange(lineRange, glyphRange);
73
+ if (intersect.length == 0)
74
+ return;
75
+
76
+ BOOL isFirst = (intersect.location == glyphRange.location);
77
+ BOOL isLast = (NSMaxRange(intersect) == NSMaxRange(glyphRange));
78
+
79
+ CGRect finalRect;
80
+ if (isFirst || isLast) {
81
+ // Precise bounds are only required for the start and end of the span
82
+ CGRect textRect = [layoutManager boundingRectForGlyphRange:intersect
83
+ inTextContainer:textContainer];
84
+ finalRect = CGRectMake(textRect.origin.x + origin.x, textRect.origin.y + origin.y,
85
+ textRect.size.width, textRect.size.height);
86
+
87
+ // For multi-line, extend the first line to the right edge of the fragment
88
+ if (isFirst && !isLast) {
89
+ finalRect.size.width =
90
+ (usedRect.origin.x + usedRect.size.width + origin.x) - finalRect.origin.x;
91
+ }
92
+ } else {
93
+ // OPTIMIZATION: Middle lines use the usedRect of the fragment directly
94
+ finalRect = CGRectMake(usedRect.origin.x + origin.x, usedRect.origin.y + origin.y,
95
+ usedRect.size.width, usedRect.size.height);
96
+ }
97
+
98
+ // Ensure consistent height and no gaps
99
+ if (finalRect.size.height < referenceHeight) {
100
+ finalRect.size.height = referenceHeight;
101
+ }
102
+
103
+ [self drawBackgroundAndBorders:finalRect
104
+ backgroundColor:backgroundColor
105
+ borderColor:borderColor
106
+ isFirst:isFirst
107
+ isLast:isLast];
108
+ }];
109
+ }
110
+
111
+ #pragma mark - Drawing Logic
112
+
113
+ - (void)drawBackgroundAndBorders:(CGRect)rect
114
+ backgroundColor:(RCTUIColor *)backgroundColor
115
+ borderColor:(RCTUIColor *)borderColor
116
+ isFirst:(BOOL)isFirst
117
+ isLast:(BOOL)isLast
118
+ {
119
+ UIBezierPath *path = [self pathForRect:rect isFirst:isFirst isLast:isLast];
120
+ [backgroundColor setFill];
121
+ [path fill];
122
+
123
+ if (borderColor) {
124
+ [borderColor setStroke];
125
+ UIBezierPath *strokePath =
126
+ (isFirst && isLast) ? path : [self openBorderPathForRect:rect isFirst:isFirst isLast:isLast];
127
+ strokePath.lineWidth = kCodeBackgroundBorderWidth;
128
+ BezierPathSetRoundStyle(strokePath);
129
+ [strokePath stroke];
130
+ }
131
+ }
132
+
133
+ - (UIBezierPath *)pathForRect:(CGRect)rect isFirst:(BOOL)isFirst isLast:(BOOL)isLast
134
+ {
135
+ #if !TARGET_OS_OSX
136
+ UIRectCorner corners = 0;
137
+ if (isFirst)
138
+ corners |= (UIRectCornerTopLeft | UIRectCornerBottomLeft);
139
+ if (isLast)
140
+ corners |= (UIRectCornerTopRight | UIRectCornerBottomRight);
141
+
142
+ return [UIBezierPath bezierPathWithRoundedRect:rect
143
+ byRoundingCorners:corners
144
+ cornerRadii:CGSizeMake(kCodeBackgroundCornerRadius, kCodeBackgroundCornerRadius)];
145
+ #else
146
+ // NSBezierPath doesn't support per-corner rounding — use uniform corner radius
147
+ CGFloat cornerRadius = (isFirst || isLast) ? kCodeBackgroundCornerRadius : 0;
148
+ return UIBezierPathWithRoundedRect(rect, cornerRadius);
149
+ #endif
150
+ }
151
+
152
+ - (UIBezierPath *)openBorderPathForRect:(CGRect)rect isFirst:(BOOL)isFirst isLast:(BOOL)isLast
153
+ {
154
+ UIBezierPath *path = [UIBezierPath bezierPath];
155
+ CGFloat r = kCodeBackgroundCornerRadius;
156
+ CGFloat inset = kCodeBackgroundBorderWidth / 2.0;
157
+ CGRect insetRect = CGRectInset(rect, inset, inset);
158
+
159
+ if (isFirst) {
160
+ [path moveToPoint:CGPointMake(CGRectGetMaxX(rect), insetRect.origin.y)];
161
+ BezierPathAddLine(path, CGPointMake(insetRect.origin.x + r, insetRect.origin.y));
162
+ BezierPathAddQuadCurve(path, CGPointMake(insetRect.origin.x, insetRect.origin.y + r),
163
+ CGPointMake(insetRect.origin.x, insetRect.origin.y));
164
+ BezierPathAddLine(path, CGPointMake(insetRect.origin.x, CGRectGetMaxY(insetRect) - r));
165
+ BezierPathAddQuadCurve(path, CGPointMake(insetRect.origin.x + r, CGRectGetMaxY(insetRect)),
166
+ CGPointMake(insetRect.origin.x, CGRectGetMaxY(insetRect)));
167
+ BezierPathAddLine(path, CGPointMake(CGRectGetMaxX(rect), CGRectGetMaxY(insetRect)));
168
+ } else if (isLast) {
169
+ [path moveToPoint:CGPointMake(rect.origin.x, insetRect.origin.y)];
170
+ BezierPathAddLine(path, CGPointMake(CGRectGetMaxX(insetRect) - r, insetRect.origin.y));
171
+ BezierPathAddQuadCurve(path, CGPointMake(CGRectGetMaxX(insetRect), insetRect.origin.y + r),
172
+ CGPointMake(CGRectGetMaxX(insetRect), insetRect.origin.y));
173
+ BezierPathAddLine(path, CGPointMake(CGRectGetMaxX(insetRect), CGRectGetMaxY(insetRect) - r));
174
+ BezierPathAddQuadCurve(path, CGPointMake(CGRectGetMaxX(insetRect) - r, CGRectGetMaxY(insetRect)),
175
+ CGPointMake(CGRectGetMaxX(insetRect), CGRectGetMaxY(insetRect)));
176
+ BezierPathAddLine(path, CGPointMake(rect.origin.x, CGRectGetMaxY(insetRect)));
177
+ } else {
178
+ [path moveToPoint:CGPointMake(rect.origin.x, insetRect.origin.y)];
179
+ BezierPathAddLine(path, CGPointMake(CGRectGetMaxX(rect), insetRect.origin.y));
180
+ [path moveToPoint:CGPointMake(rect.origin.x, CGRectGetMaxY(insetRect))];
181
+ BezierPathAddLine(path, CGPointMake(CGRectGetMaxX(rect), CGRectGetMaxY(insetRect)));
182
+ }
183
+ return path;
184
+ }
185
+
186
+ #pragma mark - Helpers
187
+
188
+ - (CGFloat)findReferenceHeightForRange:(NSRange)range textStorage:(NSTextStorage *)textStorage
189
+ {
190
+ if (range.location == NSNotFound || range.length == 0 || !textStorage) {
191
+ return [_config paragraphFontSize] * 1.2;
192
+ }
193
+ NSNumber *lineHeightValue = [textStorage attribute:@"BlockLineHeight" atIndex:range.location effectiveRange:NULL];
194
+ return lineHeightValue ? [lineHeightValue doubleValue] : ([_config paragraphFontSize] * 1.2);
195
+ }
196
+
197
+ @end
@@ -0,0 +1,17 @@
1
+ #pragma once
2
+ #import "ENRMUIKit.h"
3
+ #import "StyleConfig.h"
4
+
5
+ NS_ASSUME_NONNULL_BEGIN
6
+
7
+ @interface CodeBlockBackground : NSObject
8
+
9
+ - (instancetype)initWithConfig:(StyleConfig *)config;
10
+ - (void)drawBackgroundsForGlyphRange:(NSRange)glyphsToShow
11
+ layoutManager:(NSLayoutManager *)layoutManager
12
+ textContainer:(NSTextContainer *)textContainer
13
+ atPoint:(CGPoint)origin;
14
+
15
+ @end
16
+
17
+ NS_ASSUME_NONNULL_END