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

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (327) hide show
  1. package/LICENSE +20 -20
  2. package/README.md +140 -140
  3. package/ReactNativeRenderRichText.podspec +23 -23
  4. package/android/build.gradle +86 -86
  5. package/android/consumer-rules.pro +3 -3
  6. package/android/src/main/AndroidManifest.xml +2 -2
  7. package/android/src/main/java/com/renderrichtext/EnrichedTiptapTextLayoutManager.kt +24 -24
  8. package/android/src/main/java/com/renderrichtext/EnrichedTiptapTextPackage.kt +13 -13
  9. package/android/src/main/java/com/renderrichtext/MeasurementStore.kt +644 -644
  10. package/android/src/main/java/com/renderrichtext/accessibility/AccessibilityLabels.kt +17 -17
  11. package/android/src/main/java/com/renderrichtext/accessibility/AccessibleTiptapTextView.kt +112 -112
  12. package/android/src/main/java/com/renderrichtext/accessibility/TiptapAccessibilityHelper.kt +576 -576
  13. package/android/src/main/java/com/renderrichtext/events/CodeBlockPressEvent.kt +24 -24
  14. package/android/src/main/java/com/renderrichtext/events/ContextMenuItemPressEvent.kt +28 -28
  15. package/android/src/main/java/com/renderrichtext/events/CopyPressEvent.kt +24 -24
  16. package/android/src/main/java/com/renderrichtext/events/ImagePressEvent.kt +25 -25
  17. package/android/src/main/java/com/renderrichtext/events/LatexErrorEvent.kt +29 -29
  18. package/android/src/main/java/com/renderrichtext/events/LinkLongPressEvent.kt +23 -23
  19. package/android/src/main/java/com/renderrichtext/events/LinkPressEvent.kt +23 -23
  20. package/android/src/main/java/com/renderrichtext/events/MentionLongPressEvent.kt +25 -25
  21. package/android/src/main/java/com/renderrichtext/events/MentionPressEvent.kt +25 -25
  22. package/android/src/main/java/com/renderrichtext/events/TaskListItemPressEvent.kt +26 -26
  23. package/android/src/main/java/com/renderrichtext/math/LatexErrorReporter.kt +9 -9
  24. package/android/src/main/java/com/renderrichtext/parser/Parser.kt +59 -59
  25. package/android/src/main/java/com/renderrichtext/parser/TextLinkMatching.kt +35 -35
  26. package/android/src/main/java/com/renderrichtext/renderer/BaselineShiftRenderer.kt +45 -45
  27. package/android/src/main/java/com/renderrichtext/renderer/BlankLineRenderer.kt +39 -39
  28. package/android/src/main/java/com/renderrichtext/renderer/BlockquoteRenderer.kt +243 -243
  29. package/android/src/main/java/com/renderrichtext/renderer/BlockquoteTextRenderer.kt +56 -56
  30. package/android/src/main/java/com/renderrichtext/renderer/CodeBlockRenderer.kt +135 -135
  31. package/android/src/main/java/com/renderrichtext/renderer/CodeRenderer.kt +37 -37
  32. package/android/src/main/java/com/renderrichtext/renderer/EmphasisRenderer.kt +28 -28
  33. package/android/src/main/java/com/renderrichtext/renderer/HeadingRenderer.kt +81 -81
  34. package/android/src/main/java/com/renderrichtext/renderer/HighlightRenderer.kt +26 -26
  35. package/android/src/main/java/com/renderrichtext/renderer/LineBreakRenderer.kt +17 -17
  36. package/android/src/main/java/com/renderrichtext/renderer/LinkRenderer.kt +90 -90
  37. package/android/src/main/java/com/renderrichtext/renderer/ListContextManager.kt +109 -109
  38. package/android/src/main/java/com/renderrichtext/renderer/ListItemRenderer.kt +211 -211
  39. package/android/src/main/java/com/renderrichtext/renderer/ListRenderer.kt +133 -133
  40. package/android/src/main/java/com/renderrichtext/renderer/MentionRenderer.kt +85 -85
  41. package/android/src/main/java/com/renderrichtext/renderer/ParagraphRenderer.kt +91 -91
  42. package/android/src/main/java/com/renderrichtext/renderer/Renderer.kt +148 -148
  43. package/android/src/main/java/com/renderrichtext/renderer/SoftBreakRenderer.kt +17 -17
  44. package/android/src/main/java/com/renderrichtext/renderer/SpanStyleCache.kt +143 -143
  45. package/android/src/main/java/com/renderrichtext/renderer/StrikethroughRenderer.kt +28 -28
  46. package/android/src/main/java/com/renderrichtext/renderer/StrongRenderer.kt +28 -28
  47. package/android/src/main/java/com/renderrichtext/renderer/TextRenderer.kt +31 -31
  48. package/android/src/main/java/com/renderrichtext/renderer/ThematicBreakRenderer.kt +46 -46
  49. package/android/src/main/java/com/renderrichtext/renderer/UnderlineRenderer.kt +28 -28
  50. package/android/src/main/java/com/renderrichtext/spans/BaseListSpan.kt +164 -164
  51. package/android/src/main/java/com/renderrichtext/spans/BaselineShiftSpan.kt +27 -27
  52. package/android/src/main/java/com/renderrichtext/spans/BlockquoteSpan.kt +302 -302
  53. package/android/src/main/java/com/renderrichtext/spans/CodeBackgroundSpan.kt +205 -205
  54. package/android/src/main/java/com/renderrichtext/spans/CodeBlockSpan.kt +216 -216
  55. package/android/src/main/java/com/renderrichtext/spans/CodeSpan.kt +32 -32
  56. package/android/src/main/java/com/renderrichtext/spans/EmphasisSpan.kt +42 -42
  57. package/android/src/main/java/com/renderrichtext/spans/FadeInSpan.kt +29 -29
  58. package/android/src/main/java/com/renderrichtext/spans/HeadingSpan.kt +38 -38
  59. package/android/src/main/java/com/renderrichtext/spans/HighlightSpan.kt +80 -80
  60. package/android/src/main/java/com/renderrichtext/spans/ImageSpan.kt +481 -481
  61. package/android/src/main/java/com/renderrichtext/spans/InlineBackgroundGeometry.kt +42 -42
  62. package/android/src/main/java/com/renderrichtext/spans/LineHeightSpan.kt +39 -39
  63. package/android/src/main/java/com/renderrichtext/spans/LinkPillIconCache.kt +154 -154
  64. package/android/src/main/java/com/renderrichtext/spans/LinkPillSpan.kt +381 -381
  65. package/android/src/main/java/com/renderrichtext/spans/LinkSpan.kt +68 -68
  66. package/android/src/main/java/com/renderrichtext/spans/ListItemSpacingSpan.kt +33 -33
  67. package/android/src/main/java/com/renderrichtext/spans/ListMarkerAnchorSpan.kt +38 -38
  68. package/android/src/main/java/com/renderrichtext/spans/MarginBottomSpan.kt +76 -76
  69. package/android/src/main/java/com/renderrichtext/spans/MentionChipSpan.kt +132 -132
  70. package/android/src/main/java/com/renderrichtext/spans/MentionSpan.kt +46 -46
  71. package/android/src/main/java/com/renderrichtext/spans/OrderedListSpan.kt +127 -127
  72. package/android/src/main/java/com/renderrichtext/spans/SpoilerSpan.kt +33 -33
  73. package/android/src/main/java/com/renderrichtext/spans/StrikethroughSpan.kt +12 -12
  74. package/android/src/main/java/com/renderrichtext/spans/StrongSpan.kt +39 -39
  75. package/android/src/main/java/com/renderrichtext/spans/TaskListSpan.kt +143 -143
  76. package/android/src/main/java/com/renderrichtext/spans/TextSpan.kt +26 -26
  77. package/android/src/main/java/com/renderrichtext/spans/ThematicBreakSpan.kt +69 -69
  78. package/android/src/main/java/com/renderrichtext/spans/UnorderedListSpan.kt +96 -96
  79. package/android/src/main/java/com/renderrichtext/spoiler/SpoilerStubs.kt +46 -46
  80. package/android/src/main/java/com/renderrichtext/styles/BaseBlockStyle.kt +11 -11
  81. package/android/src/main/java/com/renderrichtext/styles/BlockquoteStyle.kt +83 -83
  82. package/android/src/main/java/com/renderrichtext/styles/CodeBlockStyle.kt +80 -80
  83. package/android/src/main/java/com/renderrichtext/styles/CodeStyle.kt +26 -26
  84. package/android/src/main/java/com/renderrichtext/styles/EmphasisStyle.kt +21 -21
  85. package/android/src/main/java/com/renderrichtext/styles/FactoidStyle.kt +21 -21
  86. package/android/src/main/java/com/renderrichtext/styles/HeadingStyle.kt +33 -33
  87. package/android/src/main/java/com/renderrichtext/styles/HighlightStyle.kt +19 -19
  88. package/android/src/main/java/com/renderrichtext/styles/ImageStyle.kt +29 -29
  89. package/android/src/main/java/com/renderrichtext/styles/InlineImageStyle.kt +17 -17
  90. package/android/src/main/java/com/renderrichtext/styles/InlineMathStyle.kt +17 -17
  91. package/android/src/main/java/com/renderrichtext/styles/LinkPillContent.kt +36 -36
  92. package/android/src/main/java/com/renderrichtext/styles/LinkPillStyle.kt +44 -44
  93. package/android/src/main/java/com/renderrichtext/styles/LinkStyle.kt +23 -23
  94. package/android/src/main/java/com/renderrichtext/styles/LinkVariantEntry.kt +34 -34
  95. package/android/src/main/java/com/renderrichtext/styles/ListStyle.kt +65 -65
  96. package/android/src/main/java/com/renderrichtext/styles/MathStyle.kt +29 -29
  97. package/android/src/main/java/com/renderrichtext/styles/MentionStyle.kt +19 -19
  98. package/android/src/main/java/com/renderrichtext/styles/ParagraphStyle.kt +33 -33
  99. package/android/src/main/java/com/renderrichtext/styles/SpoilerStyle.kt +27 -27
  100. package/android/src/main/java/com/renderrichtext/styles/StrikethroughStyle.kt +17 -17
  101. package/android/src/main/java/com/renderrichtext/styles/StrongStyle.kt +21 -21
  102. package/android/src/main/java/com/renderrichtext/styles/StyleConfig.kt +411 -411
  103. package/android/src/main/java/com/renderrichtext/styles/StyleParser.kt +92 -92
  104. package/android/src/main/java/com/renderrichtext/styles/SubscriptStyle.kt +16 -16
  105. package/android/src/main/java/com/renderrichtext/styles/SuperscriptStyle.kt +16 -16
  106. package/android/src/main/java/com/renderrichtext/styles/TableStyle.kt +75 -75
  107. package/android/src/main/java/com/renderrichtext/styles/TaskListStyle.kt +29 -29
  108. package/android/src/main/java/com/renderrichtext/styles/TextAlignment.kt +32 -32
  109. package/android/src/main/java/com/renderrichtext/styles/ThematicBreakStyle.kt +23 -23
  110. package/android/src/main/java/com/renderrichtext/styles/UnderlineStyle.kt +17 -17
  111. package/android/src/main/java/com/renderrichtext/styles/VideoStyle.kt +31 -31
  112. package/android/src/main/java/com/renderrichtext/utils/common/BorderStyleUtils.kt +86 -86
  113. package/android/src/main/java/com/renderrichtext/utils/common/BreakStrategyUtils.kt +32 -32
  114. package/android/src/main/java/com/renderrichtext/utils/common/CodeBlockHighlighter.kt +36 -36
  115. package/android/src/main/java/com/renderrichtext/utils/common/CodeBlockNode.kt +42 -42
  116. package/android/src/main/java/com/renderrichtext/utils/common/EllipsizeUtils.kt +27 -27
  117. package/android/src/main/java/com/renderrichtext/utils/common/EnrichedTiptapAncestorUtils.kt +10 -10
  118. package/android/src/main/java/com/renderrichtext/utils/common/FeatureFlags.kt +9 -9
  119. package/android/src/main/java/com/renderrichtext/utils/common/LinkRecognitionProps.kt +31 -31
  120. package/android/src/main/java/com/renderrichtext/utils/common/LinkRegexConfig.kt +56 -56
  121. package/android/src/main/java/com/renderrichtext/utils/common/MotionPreferences.kt +18 -18
  122. package/android/src/main/java/com/renderrichtext/utils/common/ReadableMapExtensions.kt +28 -28
  123. package/android/src/main/java/com/renderrichtext/utils/common/layout/RTLUtils.kt +6 -6
  124. package/android/src/main/java/com/renderrichtext/utils/common/serialization/TiptapASTSerializer.kt +368 -368
  125. package/android/src/main/java/com/renderrichtext/utils/text/ImageCache.kt +88 -88
  126. package/android/src/main/java/com/renderrichtext/utils/text/ImageDownloader.kt +203 -203
  127. package/android/src/main/java/com/renderrichtext/utils/text/LocalImageLoader.kt +167 -167
  128. package/android/src/main/java/com/renderrichtext/utils/text/TailFadeInAnimator.kt +84 -84
  129. package/android/src/main/java/com/renderrichtext/utils/text/conversion/HTMLGenerator.kt +1105 -1105
  130. package/android/src/main/java/com/renderrichtext/utils/text/conversion/TiptapExtractor.kt +423 -423
  131. package/android/src/main/java/com/renderrichtext/utils/text/extensions/ParagraphUtils.kt +9 -9
  132. package/android/src/main/java/com/renderrichtext/utils/text/extensions/SpannableExtensions.kt +9 -9
  133. package/android/src/main/java/com/renderrichtext/utils/text/extensions/TextPaintExtensions.kt +76 -76
  134. package/android/src/main/java/com/renderrichtext/utils/text/interaction/CheckboxTouchHelper.kt +61 -61
  135. package/android/src/main/java/com/renderrichtext/utils/text/interaction/TaskListTapUtils.kt +286 -286
  136. package/android/src/main/java/com/renderrichtext/utils/text/span/ApplyLineHeight.kt +39 -39
  137. package/android/src/main/java/com/renderrichtext/utils/text/span/BlockSpacing.kt +142 -142
  138. package/android/src/main/java/com/renderrichtext/utils/text/span/SpanFlags.kt +43 -43
  139. package/android/src/main/java/com/renderrichtext/utils/text/span/WidthAwareSpans.kt +30 -30
  140. package/android/src/main/java/com/renderrichtext/utils/text/view/CodeBlockPressHost.kt +15 -15
  141. package/android/src/main/java/com/renderrichtext/utils/text/view/ImagePressHost.kt +19 -19
  142. package/android/src/main/java/com/renderrichtext/utils/text/view/SelectionActionMode.kt +235 -235
  143. package/android/src/main/java/com/renderrichtext/utils/text/view/TextSelectionColors.kt +48 -48
  144. package/android/src/main/java/com/renderrichtext/utils/text/view/TextViewSetup.kt +119 -119
  145. package/android/src/main/java/com/renderrichtext/views/ContextMenuPopup.kt +217 -217
  146. package/android/src/main/java/com/renderrichtext/views/CopyGlyph.kt +101 -101
  147. package/android/src/main/java/com/renderrichtext/views/WrapGlyph.kt +40 -40
  148. package/android/src/main/jni/CMakeLists.txt +52 -52
  149. package/android/src/main/jni/react/renderer/components/RichTextSpec/ComponentDescriptors.h +30 -30
  150. package/android/src/main/jni/react/renderer/components/RichTextSpec/TiptapTextComponentDescriptor.h +29 -29
  151. package/android/src/main/jni/react/renderer/components/RichTextSpec/TiptapTextMeasurementManager.cpp +45 -45
  152. package/android/src/main/jni/react/renderer/components/RichTextSpec/TiptapTextMeasurementManager.h +21 -21
  153. package/android/src/main/jni/react/renderer/components/RichTextSpec/TiptapTextShadowNode.cpp +38 -38
  154. package/android/src/main/jni/react/renderer/components/RichTextSpec/TiptapTextShadowNode.h +53 -53
  155. package/android/src/main/jni/react/renderer/components/RichTextSpec/TiptapTextState.cpp +9 -9
  156. package/android/src/main/jni/react/renderer/components/RichTextSpec/TiptapTextState.h +24 -24
  157. package/android/src/main/jni/react/renderer/components/RichTextSpec/conversions.h +40 -40
  158. package/cpp/parser/TiptapParser.hpp +13 -13
  159. package/cpp/vendor/nlohmann/json.hpp +24765 -24765
  160. package/ios/EnrichedTiptapText.h +27 -27
  161. package/ios/attachments/ENRMImageAttachment.h +51 -51
  162. package/ios/attachments/ENRMImageAttachment.m +398 -398
  163. package/ios/attachments/ENRMLinkPillAttachment.h +47 -47
  164. package/ios/attachments/ENRMLinkPillAttachment.m +324 -324
  165. package/ios/attachments/ENRMLinkPillIconCache.h +28 -28
  166. package/ios/attachments/ENRMLinkPillIconCache.m +181 -181
  167. package/ios/attachments/ENRMLinkPillText.h +27 -27
  168. package/ios/attachments/ENRMLinkPillText.m +118 -118
  169. package/ios/attachments/ENRMMathInlineAttachment.h +7 -7
  170. package/ios/attachments/ENRMMathInlineAttachment.m +4 -4
  171. package/ios/attachments/ThematicBreakAttachment.h +15 -15
  172. package/ios/attachments/ThematicBreakAttachment.m +33 -33
  173. package/ios/internals/ENRMViewFreeMeasurement.h +208 -208
  174. package/ios/internals/EnrichedTiptapTextComponentDescriptor.h +19 -19
  175. package/ios/internals/EnrichedTiptapTextShadowNode.h +43 -43
  176. package/ios/internals/EnrichedTiptapTextShadowNode.mm +69 -69
  177. package/ios/internals/EnrichedTiptapTextState.h +24 -24
  178. package/ios/internals/MeasurementCache.h +308 -308
  179. package/ios/internals/ShadowMeasurementUtils.h +145 -145
  180. package/ios/parser/ENRMTextLinkAttributes.h +7 -7
  181. package/ios/parser/ENRMTiptapParser.h +33 -33
  182. package/ios/parser/ENRMTiptapParser.mm +73 -73
  183. package/ios/parser/TiptapASTNode.m +52 -52
  184. package/ios/renderer/AttributedRenderer.h +23 -23
  185. package/ios/renderer/AttributedRenderer.m +229 -229
  186. package/ios/renderer/BaseRenderer.h +33 -33
  187. package/ios/renderer/BaseRenderer.m +46 -46
  188. package/ios/renderer/BaselineShiftTextAttributes.h +10 -10
  189. package/ios/renderer/BaselineShiftTextAttributes.m +26 -26
  190. package/ios/renderer/BlankLineRenderer.h +4 -4
  191. package/ios/renderer/BlankLineRenderer.m +51 -51
  192. package/ios/renderer/BlockquoteRenderer.h +6 -6
  193. package/ios/renderer/BlockquoteRenderer.m +258 -258
  194. package/ios/renderer/CodeBlockRenderer.h +9 -9
  195. package/ios/renderer/CodeBlockRenderer.m +99 -99
  196. package/ios/renderer/CodeRenderer.h +9 -9
  197. package/ios/renderer/CodeRenderer.m +69 -69
  198. package/ios/renderer/ENRMBlockquoteTextRenderer.h +25 -25
  199. package/ios/renderer/ENRMBlockquoteTextRenderer.m +48 -48
  200. package/ios/renderer/EmphasisRenderer.h +5 -5
  201. package/ios/renderer/EmphasisRenderer.m +99 -99
  202. package/ios/renderer/HeadingRenderer.h +6 -6
  203. package/ios/renderer/HeadingRenderer.m +102 -102
  204. package/ios/renderer/HighlightRenderer.h +7 -7
  205. package/ios/renderer/HighlightRenderer.m +33 -33
  206. package/ios/renderer/LinkRenderer.h +6 -6
  207. package/ios/renderer/LinkRenderer.m +157 -157
  208. package/ios/renderer/ListItemRenderer.h +24 -24
  209. package/ios/renderer/ListItemRenderer.m +283 -283
  210. package/ios/renderer/ListRenderer.h +13 -13
  211. package/ios/renderer/ListRenderer.m +126 -126
  212. package/ios/renderer/MentionRenderer.h +9 -9
  213. package/ios/renderer/MentionRenderer.m +96 -96
  214. package/ios/renderer/NodeRenderer.h +8 -8
  215. package/ios/renderer/ParagraphRenderer.h +6 -6
  216. package/ios/renderer/ParagraphRenderer.m +85 -85
  217. package/ios/renderer/RenderContext.h +145 -145
  218. package/ios/renderer/RenderContext.m +402 -402
  219. package/ios/renderer/RendererFactory.h +12 -12
  220. package/ios/renderer/StrikethroughRenderer.h +5 -5
  221. package/ios/renderer/StrikethroughRenderer.m +30 -30
  222. package/ios/renderer/StrongRenderer.h +5 -5
  223. package/ios/renderer/StrongRenderer.m +87 -87
  224. package/ios/renderer/TextRenderer.h +6 -6
  225. package/ios/renderer/TextRenderer.m +18 -18
  226. package/ios/renderer/ThematicBreakRenderer.h +4 -4
  227. package/ios/renderer/ThematicBreakRenderer.m +41 -41
  228. package/ios/renderer/UnderlineRenderer.h +4 -4
  229. package/ios/renderer/UnderlineRenderer.m +41 -41
  230. package/ios/styles/ENRMFontSlot.h +12 -12
  231. package/ios/styles/ENRMFontSlot.m +24 -24
  232. package/ios/styles/StyleConfig.h +488 -488
  233. package/ios/styles/StyleConfig.mm +2820 -2820
  234. package/ios/utils/AccessibilityInfo.h +35 -35
  235. package/ios/utils/AccessibilityInfo.m +24 -24
  236. package/ios/utils/BlockquoteBorder.h +26 -26
  237. package/ios/utils/BlockquoteBorder.m +294 -294
  238. package/ios/utils/CodeBackground.h +19 -19
  239. package/ios/utils/CodeBackground.m +196 -196
  240. package/ios/utils/CodeBlockBackground.h +17 -17
  241. package/ios/utils/CodeBlockBackground.m +102 -102
  242. package/ios/utils/ContextMenuUtils.h +76 -76
  243. package/ios/utils/ContextMenuUtils.mm +75 -75
  244. package/ios/utils/ENRMAccessibilityLabels.h +40 -40
  245. package/ios/utils/ENRMAccessibilityLabels.m +5 -5
  246. package/ios/utils/ENRMAsyncRenderCoordinator.h +24 -24
  247. package/ios/utils/ENRMAsyncRenderCoordinator.m +37 -37
  248. package/ios/utils/ENRMAtomicSize.h +65 -65
  249. package/ios/utils/ENRMCodeBlockContent.h +37 -37
  250. package/ios/utils/ENRMCodeBlockContent.mm +89 -89
  251. package/ios/utils/ENRMFeatureFlags.h +25 -25
  252. package/ios/utils/ENRMImageDownloader.h +30 -30
  253. package/ios/utils/ENRMImageDownloader.m +168 -168
  254. package/ios/utils/ENRMLatexErrorCoordinator.h +27 -27
  255. package/ios/utils/ENRMLatexErrorCoordinator.mm +75 -75
  256. package/ios/utils/ENRMLatexErrorReporting.h +13 -13
  257. package/ios/utils/ENRMLinkContextMenus.h +93 -93
  258. package/ios/utils/ENRMLinkContextMenus.m +178 -178
  259. package/ios/utils/ENRMLinkRegexConfig.h +30 -30
  260. package/ios/utils/ENRMLinkRegexConfig.mm +104 -104
  261. package/ios/utils/ENRMLinkRegexProps.h +23 -23
  262. package/ios/utils/ENRMLocalImageLoader.h +35 -35
  263. package/ios/utils/ENRMLocalImageLoader.m +111 -111
  264. package/ios/utils/ENRMMenuAction.h +27 -27
  265. package/ios/utils/ENRMMenuAction.m +33 -33
  266. package/ios/utils/ENRMSpoilerOverlayManager.h +15 -15
  267. package/ios/utils/ENRMSpoilerOverlayManager.m +19 -19
  268. package/ios/utils/ENRMSpoilerTapUtils.h +6 -6
  269. package/ios/utils/ENRMSpoilerTapUtils.m +11 -11
  270. package/ios/utils/ENRMTailFadeInAnimator.h +16 -16
  271. package/ios/utils/ENRMTailFadeInAnimator.m +161 -161
  272. package/ios/utils/ENRMTextHitTest.h +23 -23
  273. package/ios/utils/ENRMTextHitTest.m +20 -20
  274. package/ios/utils/ENRMTextInteractionUtils.h +20 -20
  275. package/ios/utils/ENRMTextInteractionUtils.m +15 -15
  276. package/ios/utils/ENRMTextRenderer.h +38 -38
  277. package/ios/utils/ENRMTextRenderer.m +54 -54
  278. package/ios/utils/ENRMTextViewSetup.h +132 -132
  279. package/ios/utils/ENRMUIKit.h +429 -429
  280. package/ios/utils/EditMenuUtils.h +105 -105
  281. package/ios/utils/EditMenuUtils.m +143 -143
  282. package/ios/utils/FontScaleObserver.h +10 -10
  283. package/ios/utils/FontScaleObserver.m +55 -55
  284. package/ios/utils/FontUtils.h +31 -31
  285. package/ios/utils/FontUtils.m +63 -63
  286. package/ios/utils/HTMLGenerator.h +25 -25
  287. package/ios/utils/HTMLGenerator.m +1041 -1041
  288. package/ios/utils/HeightUpdateUtils.h +25 -25
  289. package/ios/utils/ImageRequestHeaderUtils.h +35 -35
  290. package/ios/utils/LastElementUtils.h +97 -97
  291. package/ios/utils/LinkContextMenuUtils.h +55 -55
  292. package/ios/utils/LinkPillContentUtils.h +46 -46
  293. package/ios/utils/ListMarkerDrawer.h +15 -15
  294. package/ios/utils/ListMarkerDrawer.m +239 -239
  295. package/ios/utils/MentionBackground.h +26 -26
  296. package/ios/utils/MentionBackground.m +86 -86
  297. package/ios/utils/ParagraphStyleUtils.h +87 -87
  298. package/ios/utils/ParagraphStyleUtils.m +484 -484
  299. package/ios/utils/PasteboardUtils.h +48 -48
  300. package/ios/utils/PasteboardUtils.m +166 -166
  301. package/ios/utils/RTFExportUtils.h +24 -24
  302. package/ios/utils/RTFExportUtils.m +299 -299
  303. package/ios/utils/SelectionColorUtils.h +14 -14
  304. package/ios/utils/StylePropsUtils.h +1340 -1340
  305. package/ios/utils/TaskListTapUtils.h +6 -6
  306. package/ios/utils/TaskListTapUtils.m +14 -14
  307. package/ios/utils/TextViewLayoutManager.h +14 -14
  308. package/ios/utils/TiptapAccessibilityElementBuilder.h +43 -43
  309. package/ios/utils/TiptapAccessibilityElementBuilder.m +432 -432
  310. package/ios/utils/TiptapExtractor.h +17 -17
  311. package/ios/utils/TiptapExtractor.m +367 -367
  312. package/ios/views/ENRMTiptapTextView.h +25 -25
  313. package/ios/views/ENRMTiptapTextView.m +247 -247
  314. package/package.json +65 -70
  315. package/react-native.config.js +10 -10
  316. package/src/admonitionDefaults.ts +58 -58
  317. package/src/darkModeTextStyle.ts +99 -99
  318. package/src/headingDefaults.ts +21 -21
  319. package/src/index.tsx +4 -4
  320. package/src/linkVariantUtils.ts +120 -120
  321. package/src/normalizeTiptapStyle.ts +397 -397
  322. package/src/rn-globals.d.ts +1 -1
  323. package/src/styleUtils.ts +107 -107
  324. package/src/types/TiptapStyle.ts +532 -532
  325. package/src/types/TiptapStyleInternal.ts +299 -299
  326. package/src/types/linkPill.ts +9 -9
  327. package/src/utils/isDev.ts +4 -4
@@ -1,308 +1,308 @@
1
- #pragma once
2
-
3
- #include <CoreGraphics/CGBase.h>
4
- #include <React/RCTUtils.h>
5
- #include <list>
6
- #include <mutex>
7
- #include <react/renderer/graphics/Float.h>
8
- #include <string>
9
- #include <tuple>
10
- #include <unordered_map>
11
-
12
- namespace facebook::react {
13
-
14
- struct HashUtils {
15
-
16
- static inline size_t combine(size_t h, size_t v)
17
- {
18
- return h ^ (v + 0x9e3779b97f4a7c15ULL + (h << 6) + (h >> 2));
19
- }
20
-
21
- template <typename T> static inline void hash_one(size_t &seed, const T &v)
22
- {
23
- seed = combine(seed, std::hash<T>{}(v));
24
- }
25
- };
26
-
27
- enum class TiptapFlavor : uint8_t {
28
- CommonMark = 0,
29
- GitHub = 1,
30
- };
31
-
32
- struct MeasurementCacheKey {
33
- std::string tiptap;
34
- CGFloat maxWidth;
35
- bool allowTrailingMargin;
36
- bool allowFontScaling;
37
- double maxFontSizeMultiplier;
38
- bool md4cFlagsUnderline;
39
- bool md4cFlagsSuperscript;
40
- bool md4cFlagsSubscript;
41
- bool md4cFlagsHighlight;
42
- bool md4cFlagsLatexMath;
43
- bool md4cFlagsHardSoftBreaks;
44
- bool md4cFlagsPreserveBlankLines;
45
- bool md4cFlagsAdmonitions;
46
- size_t styleFingerprint;
47
- size_t linkPillContentFingerprint;
48
- // Code blocks the user wrapped (view state, not props); 0 when none.
49
- size_t wrappedCodeBlocksFingerprint;
50
- CGFloat fontScale;
51
- TiptapFlavor flavor;
52
- std::string lineBreakStrategyIOS;
53
- std::string writingDirection;
54
- int numberOfLines;
55
- std::string ellipsizeMode;
56
- std::string linkRegexKey;
57
- std::string inlineCodeLinkRegexKey;
58
-
59
- bool operator==(const MeasurementCacheKey &other) const
60
- {
61
- return std::tie(tiptap, maxWidth, allowTrailingMargin, allowFontScaling, maxFontSizeMultiplier,
62
- md4cFlagsUnderline, md4cFlagsSuperscript, md4cFlagsSubscript, md4cFlagsHighlight,
63
- md4cFlagsLatexMath, md4cFlagsHardSoftBreaks, md4cFlagsPreserveBlankLines, md4cFlagsAdmonitions,
64
- styleFingerprint, linkPillContentFingerprint, wrappedCodeBlocksFingerprint, fontScale, flavor,
65
- lineBreakStrategyIOS, writingDirection, numberOfLines, ellipsizeMode, linkRegexKey,
66
- inlineCodeLinkRegexKey) ==
67
- std::tie(other.tiptap, other.maxWidth, other.allowTrailingMargin, other.allowFontScaling,
68
- other.maxFontSizeMultiplier, other.md4cFlagsUnderline, other.md4cFlagsSuperscript,
69
- other.md4cFlagsSubscript, other.md4cFlagsHighlight, other.md4cFlagsLatexMath,
70
- other.md4cFlagsHardSoftBreaks, other.md4cFlagsPreserveBlankLines, other.md4cFlagsAdmonitions,
71
- other.styleFingerprint, other.linkPillContentFingerprint, other.wrappedCodeBlocksFingerprint,
72
- other.fontScale, other.flavor, other.lineBreakStrategyIOS, other.writingDirection,
73
- other.numberOfLines, other.ellipsizeMode, other.linkRegexKey, other.inlineCodeLinkRegexKey);
74
- }
75
- };
76
-
77
- struct MeasurementCacheKeyHash {
78
- size_t operator()(const MeasurementCacheKey &key) const
79
- {
80
- size_t h = 0;
81
- HashUtils::hash_one(h, key.tiptap);
82
- HashUtils::hash_one(h, key.maxWidth);
83
- HashUtils::hash_one(h, key.allowTrailingMargin);
84
- HashUtils::hash_one(h, key.allowFontScaling);
85
- HashUtils::hash_one(h, key.maxFontSizeMultiplier);
86
- HashUtils::hash_one(h, key.md4cFlagsUnderline);
87
- HashUtils::hash_one(h, key.md4cFlagsSuperscript);
88
- HashUtils::hash_one(h, key.md4cFlagsSubscript);
89
- HashUtils::hash_one(h, key.md4cFlagsHighlight);
90
- HashUtils::hash_one(h, key.md4cFlagsLatexMath);
91
- HashUtils::hash_one(h, key.md4cFlagsHardSoftBreaks);
92
- HashUtils::hash_one(h, key.md4cFlagsPreserveBlankLines);
93
- HashUtils::hash_one(h, key.md4cFlagsAdmonitions);
94
- HashUtils::hash_one(h, key.styleFingerprint);
95
- HashUtils::hash_one(h, key.linkPillContentFingerprint);
96
- HashUtils::hash_one(h, key.wrappedCodeBlocksFingerprint);
97
- HashUtils::hash_one(h, key.fontScale);
98
- HashUtils::hash_one(h, static_cast<uint8_t>(key.flavor));
99
- HashUtils::hash_one(h, key.lineBreakStrategyIOS);
100
- HashUtils::hash_one(h, key.writingDirection);
101
- HashUtils::hash_one(h, key.numberOfLines);
102
- HashUtils::hash_one(h, key.ellipsizeMode);
103
- HashUtils::hash_one(h, key.linkRegexKey);
104
- HashUtils::hash_one(h, key.inlineCodeLinkRegexKey);
105
- return h;
106
- }
107
- };
108
-
109
- struct CachedSize {
110
- CGFloat width;
111
- CGFloat height;
112
- };
113
-
114
- template <typename StyleStruct> inline size_t computeStyleFingerprint(const StyleStruct &s)
115
- {
116
- size_t h = 0;
117
- auto hashFields = [&](auto... args) { (HashUtils::hash_one(h, args), ...); };
118
-
119
- auto hashTextLayout = [&](const auto &item) {
120
- hashFields(item.fontFamily, item.fontSize, item.fontWeight, item.marginTop, item.marginBottom, item.lineHeight);
121
- };
122
-
123
- // Block Elements
124
- hashTextLayout(s.paragraph);
125
- hashFields(s.paragraph.textAlign);
126
- hashTextLayout(s.h1);
127
- hashFields(s.h1.textAlign);
128
- hashTextLayout(s.h2);
129
- hashFields(s.h2.textAlign);
130
- hashTextLayout(s.h3);
131
- hashFields(s.h3.textAlign);
132
- hashTextLayout(s.h4);
133
- hashFields(s.h4.textAlign);
134
- hashTextLayout(s.h5);
135
- hashFields(s.h5.textAlign);
136
- hashTextLayout(s.h6);
137
- hashFields(s.h6.textAlign);
138
-
139
- hashTextLayout(s.blockquote);
140
- hashFields(s.blockquote.borderWidth, s.blockquote.gapWidth, s.blockquote.padding, s.blockquote.borderRadius);
141
-
142
- hashTextLayout(s.list);
143
- hashFields(s.list.bulletSize, s.list.markerMinWidth, s.list.markerFontWeight, s.list.gapWidth, s.list.marginLeft,
144
- s.list.itemSpacing);
145
-
146
- // Code & Inlines
147
- hashFields(s.codeBlock.fontFamily, s.codeBlock.fontSize, s.codeBlock.fontWeight, s.codeBlock.marginTop,
148
- s.codeBlock.marginBottom, s.codeBlock.lineHeight, s.codeBlock.padding, s.codeBlock.borderRadius,
149
- s.codeBlock.borderWidth);
150
- hashFields(s.code.fontFamily, s.code.fontSize);
151
- hashFields(s.link.fontFamily, s.strong.fontFamily, s.strong.fontWeight, s.em.fontFamily, s.em.fontStyle);
152
- // Variants change link metrics: a font family, or a pill box around the label.
153
- for (const auto &variant : s.linkVariants) {
154
- hashFields(variant.pattern, variant.fontFamily, variant.pill.enabled, variant.pill.label, variant.pill.iconUri,
155
- variant.pill.paddingHorizontal, variant.pill.paddingVertical, variant.pill.lineHeight,
156
- variant.pill.borderWidth, variant.pill.maxWidth);
157
- }
158
- hashFields(s.highlight.backgroundColor, s.highlight.color);
159
-
160
- // Visual/Spacing Elements
161
- hashFields(s.image.height, s.image.maxHeight, s.image.aspectRatio, s.image.marginTop, s.image.marginBottom);
162
- hashFields(s.video.marginTop, s.video.marginBottom, s.video.borderRadius, s.video.aspectRatio,
163
- s.video.backgroundColor);
164
- hashFields(s.inlineImage.size);
165
- hashFields(s.thematicBreak.height, s.thematicBreak.marginTop, s.thematicBreak.marginBottom);
166
-
167
- // Complex Components
168
- hashTextLayout(s.table);
169
- hashFields(s.table.headerFontFamily, s.table.cellPaddingHorizontal, s.table.cellPaddingVertical, s.table.borderWidth,
170
- s.table.borderRadius, s.table.horizontalOverflow);
171
- hashFields(s.math.fontSize, s.math.padding, s.math.marginTop, s.math.marginBottom, s.math.textAlign);
172
- hashFields(s.taskList.checkboxSize, s.taskList.checkboxBorderRadius);
173
-
174
- return h;
175
- }
176
-
177
- // Pill labels and icons (the `linkPillContent` prop) change link widths.
178
- template <typename ContentVector> inline size_t computeLinkPillContentFingerprint(const ContentVector &content)
179
- {
180
- size_t h = 0;
181
- for (const auto &entry : content) {
182
- HashUtils::hash_one(h, entry.url);
183
- HashUtils::hash_one(h, entry.label);
184
- HashUtils::hash_one(h, entry.iconUri);
185
- }
186
- return h;
187
- }
188
-
189
- template <typename RegexProps> inline std::string buildLinkRecognitionCacheKey(const RegexProps &props)
190
- {
191
- std::string key;
192
- key += props.caseInsensitive ? '1' : '0';
193
- key += props.dotAll ? '1' : '0';
194
- key += props.isDisabled ? '1' : '0';
195
- key += props.isDefault ? '1' : '0';
196
- return key + props.pattern;
197
- }
198
-
199
- template <typename PropsType>
200
- inline MeasurementCacheKey buildMeasurementCacheKey(const PropsType &props, CGFloat maxWidth, CGFloat fontScale,
201
- TiptapFlavor flavor, size_t wrappedCodeBlocksFingerprint = 0)
202
- {
203
- return MeasurementCacheKey{
204
- .tiptap = props.document,
205
- .maxWidth = maxWidth,
206
- .allowTrailingMargin = props.allowTrailingMargin,
207
- .allowFontScaling = props.allowFontScaling,
208
- .maxFontSizeMultiplier = props.maxFontSizeMultiplier,
209
- .md4cFlagsUnderline = props.md4cFlags.underline,
210
- .md4cFlagsSuperscript = props.md4cFlags.superscript,
211
- .md4cFlagsSubscript = props.md4cFlags.subscript,
212
- .md4cFlagsHighlight = props.md4cFlags.highlight,
213
- .md4cFlagsLatexMath = props.md4cFlags.latexMath,
214
- .md4cFlagsHardSoftBreaks = props.md4cFlags.hardSoftBreaks,
215
- .md4cFlagsPreserveBlankLines = props.md4cFlags.preserveBlankLines,
216
- .md4cFlagsAdmonitions = props.md4cFlags.admonitions,
217
- .styleFingerprint = computeStyleFingerprint(props.tiptapStyle),
218
- .linkPillContentFingerprint = computeLinkPillContentFingerprint(props.linkPillContent),
219
- .wrappedCodeBlocksFingerprint = wrappedCodeBlocksFingerprint,
220
- .fontScale = fontScale,
221
- .flavor = flavor,
222
- .lineBreakStrategyIOS = props.lineBreakStrategyIOS,
223
- .writingDirection = props.writingDirection,
224
- .numberOfLines = props.numberOfLines,
225
- .ellipsizeMode = props.ellipsizeMode,
226
- .linkRegexKey = buildLinkRecognitionCacheKey(props.linkRecognition.text),
227
- .inlineCodeLinkRegexKey = buildLinkRecognitionCacheKey(props.linkRecognition.inlineCode),
228
- };
229
- }
230
-
231
- /**
232
- * Thread-safe global measurement cache using an LRU (Least Recently Used) strategy.
233
- * This ensures O(1) lookups while automatically discarding the oldest entries.
234
- */
235
- class MeasurementCache {
236
- public:
237
- struct CacheEntry {
238
- MeasurementCacheKey key;
239
- CachedSize size;
240
- };
241
-
242
- static MeasurementCache &shared()
243
- {
244
- static MeasurementCache instance;
245
- return instance;
246
- }
247
-
248
- bool get(const MeasurementCacheKey &key, CachedSize &outSize)
249
- {
250
- std::lock_guard<std::mutex> lock(mutex_);
251
-
252
- auto it = map_.find(key);
253
- if (it == map_.end()) {
254
- return false;
255
- }
256
-
257
- list_.splice(list_.begin(), list_, it->second);
258
-
259
- outSize = it->second->size;
260
- return true;
261
- }
262
-
263
- void set(const MeasurementCacheKey &key, CachedSize size)
264
- {
265
- std::lock_guard<std::mutex> lock(mutex_);
266
-
267
- auto it = map_.find(key);
268
- if (it != map_.end()) {
269
- it->second->size = size;
270
- list_.splice(list_.begin(), list_, it->second);
271
- return;
272
- }
273
-
274
- list_.push_front({key, size});
275
- map_[key] = list_.begin();
276
-
277
- if (map_.size() > kMaxEntries) {
278
- auto &lastEntry = list_.back();
279
- map_.erase(lastEntry.key);
280
- list_.pop_back();
281
- }
282
- }
283
-
284
- void removeMatchingTiptap(const std::string &tiptap)
285
- {
286
- std::lock_guard<std::mutex> lock(mutex_);
287
-
288
- for (auto it = list_.begin(); it != list_.end();) {
289
- if (it->key.tiptap == tiptap) {
290
- map_.erase(it->key);
291
- it = list_.erase(it);
292
- } else {
293
- ++it;
294
- }
295
- }
296
- }
297
-
298
- private:
299
- MeasurementCache() = default;
300
-
301
- static constexpr size_t kMaxEntries = 512;
302
- mutable std::mutex mutex_;
303
-
304
- std::list<CacheEntry> list_;
305
- std::unordered_map<MeasurementCacheKey, std::list<CacheEntry>::iterator, MeasurementCacheKeyHash> map_;
306
- };
307
-
308
- } // namespace facebook::react
1
+ #pragma once
2
+
3
+ #include <CoreGraphics/CGBase.h>
4
+ #include <React/RCTUtils.h>
5
+ #include <list>
6
+ #include <mutex>
7
+ #include <react/renderer/graphics/Float.h>
8
+ #include <string>
9
+ #include <tuple>
10
+ #include <unordered_map>
11
+
12
+ namespace facebook::react {
13
+
14
+ struct HashUtils {
15
+
16
+ static inline size_t combine(size_t h, size_t v)
17
+ {
18
+ return h ^ (v + 0x9e3779b97f4a7c15ULL + (h << 6) + (h >> 2));
19
+ }
20
+
21
+ template <typename T> static inline void hash_one(size_t &seed, const T &v)
22
+ {
23
+ seed = combine(seed, std::hash<T>{}(v));
24
+ }
25
+ };
26
+
27
+ enum class TiptapFlavor : uint8_t {
28
+ CommonMark = 0,
29
+ GitHub = 1,
30
+ };
31
+
32
+ struct MeasurementCacheKey {
33
+ std::string tiptap;
34
+ CGFloat maxWidth;
35
+ bool allowTrailingMargin;
36
+ bool allowFontScaling;
37
+ double maxFontSizeMultiplier;
38
+ bool md4cFlagsUnderline;
39
+ bool md4cFlagsSuperscript;
40
+ bool md4cFlagsSubscript;
41
+ bool md4cFlagsHighlight;
42
+ bool md4cFlagsLatexMath;
43
+ bool md4cFlagsHardSoftBreaks;
44
+ bool md4cFlagsPreserveBlankLines;
45
+ bool md4cFlagsAdmonitions;
46
+ size_t styleFingerprint;
47
+ size_t linkPillContentFingerprint;
48
+ // Code blocks the user wrapped (view state, not props); 0 when none.
49
+ size_t wrappedCodeBlocksFingerprint;
50
+ CGFloat fontScale;
51
+ TiptapFlavor flavor;
52
+ std::string lineBreakStrategyIOS;
53
+ std::string writingDirection;
54
+ int numberOfLines;
55
+ std::string ellipsizeMode;
56
+ std::string linkRegexKey;
57
+ std::string inlineCodeLinkRegexKey;
58
+
59
+ bool operator==(const MeasurementCacheKey &other) const
60
+ {
61
+ return std::tie(tiptap, maxWidth, allowTrailingMargin, allowFontScaling, maxFontSizeMultiplier,
62
+ md4cFlagsUnderline, md4cFlagsSuperscript, md4cFlagsSubscript, md4cFlagsHighlight,
63
+ md4cFlagsLatexMath, md4cFlagsHardSoftBreaks, md4cFlagsPreserveBlankLines, md4cFlagsAdmonitions,
64
+ styleFingerprint, linkPillContentFingerprint, wrappedCodeBlocksFingerprint, fontScale, flavor,
65
+ lineBreakStrategyIOS, writingDirection, numberOfLines, ellipsizeMode, linkRegexKey,
66
+ inlineCodeLinkRegexKey) ==
67
+ std::tie(other.tiptap, other.maxWidth, other.allowTrailingMargin, other.allowFontScaling,
68
+ other.maxFontSizeMultiplier, other.md4cFlagsUnderline, other.md4cFlagsSuperscript,
69
+ other.md4cFlagsSubscript, other.md4cFlagsHighlight, other.md4cFlagsLatexMath,
70
+ other.md4cFlagsHardSoftBreaks, other.md4cFlagsPreserveBlankLines, other.md4cFlagsAdmonitions,
71
+ other.styleFingerprint, other.linkPillContentFingerprint, other.wrappedCodeBlocksFingerprint,
72
+ other.fontScale, other.flavor, other.lineBreakStrategyIOS, other.writingDirection,
73
+ other.numberOfLines, other.ellipsizeMode, other.linkRegexKey, other.inlineCodeLinkRegexKey);
74
+ }
75
+ };
76
+
77
+ struct MeasurementCacheKeyHash {
78
+ size_t operator()(const MeasurementCacheKey &key) const
79
+ {
80
+ size_t h = 0;
81
+ HashUtils::hash_one(h, key.tiptap);
82
+ HashUtils::hash_one(h, key.maxWidth);
83
+ HashUtils::hash_one(h, key.allowTrailingMargin);
84
+ HashUtils::hash_one(h, key.allowFontScaling);
85
+ HashUtils::hash_one(h, key.maxFontSizeMultiplier);
86
+ HashUtils::hash_one(h, key.md4cFlagsUnderline);
87
+ HashUtils::hash_one(h, key.md4cFlagsSuperscript);
88
+ HashUtils::hash_one(h, key.md4cFlagsSubscript);
89
+ HashUtils::hash_one(h, key.md4cFlagsHighlight);
90
+ HashUtils::hash_one(h, key.md4cFlagsLatexMath);
91
+ HashUtils::hash_one(h, key.md4cFlagsHardSoftBreaks);
92
+ HashUtils::hash_one(h, key.md4cFlagsPreserveBlankLines);
93
+ HashUtils::hash_one(h, key.md4cFlagsAdmonitions);
94
+ HashUtils::hash_one(h, key.styleFingerprint);
95
+ HashUtils::hash_one(h, key.linkPillContentFingerprint);
96
+ HashUtils::hash_one(h, key.wrappedCodeBlocksFingerprint);
97
+ HashUtils::hash_one(h, key.fontScale);
98
+ HashUtils::hash_one(h, static_cast<uint8_t>(key.flavor));
99
+ HashUtils::hash_one(h, key.lineBreakStrategyIOS);
100
+ HashUtils::hash_one(h, key.writingDirection);
101
+ HashUtils::hash_one(h, key.numberOfLines);
102
+ HashUtils::hash_one(h, key.ellipsizeMode);
103
+ HashUtils::hash_one(h, key.linkRegexKey);
104
+ HashUtils::hash_one(h, key.inlineCodeLinkRegexKey);
105
+ return h;
106
+ }
107
+ };
108
+
109
+ struct CachedSize {
110
+ CGFloat width;
111
+ CGFloat height;
112
+ };
113
+
114
+ template <typename StyleStruct> inline size_t computeStyleFingerprint(const StyleStruct &s)
115
+ {
116
+ size_t h = 0;
117
+ auto hashFields = [&](auto... args) { (HashUtils::hash_one(h, args), ...); };
118
+
119
+ auto hashTextLayout = [&](const auto &item) {
120
+ hashFields(item.fontFamily, item.fontSize, item.fontWeight, item.marginTop, item.marginBottom, item.lineHeight);
121
+ };
122
+
123
+ // Block Elements
124
+ hashTextLayout(s.paragraph);
125
+ hashFields(s.paragraph.textAlign);
126
+ hashTextLayout(s.h1);
127
+ hashFields(s.h1.textAlign);
128
+ hashTextLayout(s.h2);
129
+ hashFields(s.h2.textAlign);
130
+ hashTextLayout(s.h3);
131
+ hashFields(s.h3.textAlign);
132
+ hashTextLayout(s.h4);
133
+ hashFields(s.h4.textAlign);
134
+ hashTextLayout(s.h5);
135
+ hashFields(s.h5.textAlign);
136
+ hashTextLayout(s.h6);
137
+ hashFields(s.h6.textAlign);
138
+
139
+ hashTextLayout(s.blockquote);
140
+ hashFields(s.blockquote.borderWidth, s.blockquote.gapWidth, s.blockquote.padding, s.blockquote.borderRadius);
141
+
142
+ hashTextLayout(s.list);
143
+ hashFields(s.list.bulletSize, s.list.markerMinWidth, s.list.markerFontWeight, s.list.gapWidth, s.list.marginLeft,
144
+ s.list.itemSpacing);
145
+
146
+ // Code & Inlines
147
+ hashFields(s.codeBlock.fontFamily, s.codeBlock.fontSize, s.codeBlock.fontWeight, s.codeBlock.marginTop,
148
+ s.codeBlock.marginBottom, s.codeBlock.lineHeight, s.codeBlock.padding, s.codeBlock.borderRadius,
149
+ s.codeBlock.borderWidth);
150
+ hashFields(s.code.fontFamily, s.code.fontSize);
151
+ hashFields(s.link.fontFamily, s.strong.fontFamily, s.strong.fontWeight, s.em.fontFamily, s.em.fontStyle);
152
+ // Variants change link metrics: a font family, or a pill box around the label.
153
+ for (const auto &variant : s.linkVariants) {
154
+ hashFields(variant.pattern, variant.fontFamily, variant.pill.enabled, variant.pill.label, variant.pill.iconUri,
155
+ variant.pill.paddingHorizontal, variant.pill.paddingVertical, variant.pill.lineHeight,
156
+ variant.pill.borderWidth, variant.pill.maxWidth);
157
+ }
158
+ hashFields(s.highlight.backgroundColor, s.highlight.color);
159
+
160
+ // Visual/Spacing Elements
161
+ hashFields(s.image.height, s.image.maxHeight, s.image.aspectRatio, s.image.marginTop, s.image.marginBottom);
162
+ hashFields(s.video.marginTop, s.video.marginBottom, s.video.borderRadius, s.video.aspectRatio,
163
+ s.video.backgroundColor);
164
+ hashFields(s.inlineImage.size);
165
+ hashFields(s.thematicBreak.height, s.thematicBreak.marginTop, s.thematicBreak.marginBottom);
166
+
167
+ // Complex Components
168
+ hashTextLayout(s.table);
169
+ hashFields(s.table.headerFontFamily, s.table.cellPaddingHorizontal, s.table.cellPaddingVertical, s.table.borderWidth,
170
+ s.table.borderRadius, s.table.horizontalOverflow);
171
+ hashFields(s.math.fontSize, s.math.padding, s.math.marginTop, s.math.marginBottom, s.math.textAlign);
172
+ hashFields(s.taskList.checkboxSize, s.taskList.checkboxBorderRadius);
173
+
174
+ return h;
175
+ }
176
+
177
+ // Pill labels and icons (the `linkPillContent` prop) change link widths.
178
+ template <typename ContentVector> inline size_t computeLinkPillContentFingerprint(const ContentVector &content)
179
+ {
180
+ size_t h = 0;
181
+ for (const auto &entry : content) {
182
+ HashUtils::hash_one(h, entry.url);
183
+ HashUtils::hash_one(h, entry.label);
184
+ HashUtils::hash_one(h, entry.iconUri);
185
+ }
186
+ return h;
187
+ }
188
+
189
+ template <typename RegexProps> inline std::string buildLinkRecognitionCacheKey(const RegexProps &props)
190
+ {
191
+ std::string key;
192
+ key += props.caseInsensitive ? '1' : '0';
193
+ key += props.dotAll ? '1' : '0';
194
+ key += props.isDisabled ? '1' : '0';
195
+ key += props.isDefault ? '1' : '0';
196
+ return key + props.pattern;
197
+ }
198
+
199
+ template <typename PropsType>
200
+ inline MeasurementCacheKey buildMeasurementCacheKey(const PropsType &props, CGFloat maxWidth, CGFloat fontScale,
201
+ TiptapFlavor flavor, size_t wrappedCodeBlocksFingerprint = 0)
202
+ {
203
+ return MeasurementCacheKey{
204
+ .tiptap = props.document,
205
+ .maxWidth = maxWidth,
206
+ .allowTrailingMargin = props.allowTrailingMargin,
207
+ .allowFontScaling = props.allowFontScaling,
208
+ .maxFontSizeMultiplier = props.maxFontSizeMultiplier,
209
+ .md4cFlagsUnderline = props.md4cFlags.underline,
210
+ .md4cFlagsSuperscript = props.md4cFlags.superscript,
211
+ .md4cFlagsSubscript = props.md4cFlags.subscript,
212
+ .md4cFlagsHighlight = props.md4cFlags.highlight,
213
+ .md4cFlagsLatexMath = props.md4cFlags.latexMath,
214
+ .md4cFlagsHardSoftBreaks = props.md4cFlags.hardSoftBreaks,
215
+ .md4cFlagsPreserveBlankLines = props.md4cFlags.preserveBlankLines,
216
+ .md4cFlagsAdmonitions = props.md4cFlags.admonitions,
217
+ .styleFingerprint = computeStyleFingerprint(props.tiptapStyle),
218
+ .linkPillContentFingerprint = computeLinkPillContentFingerprint(props.linkPillContent),
219
+ .wrappedCodeBlocksFingerprint = wrappedCodeBlocksFingerprint,
220
+ .fontScale = fontScale,
221
+ .flavor = flavor,
222
+ .lineBreakStrategyIOS = props.lineBreakStrategyIOS,
223
+ .writingDirection = props.writingDirection,
224
+ .numberOfLines = props.numberOfLines,
225
+ .ellipsizeMode = props.ellipsizeMode,
226
+ .linkRegexKey = buildLinkRecognitionCacheKey(props.linkRecognition.text),
227
+ .inlineCodeLinkRegexKey = buildLinkRecognitionCacheKey(props.linkRecognition.inlineCode),
228
+ };
229
+ }
230
+
231
+ /**
232
+ * Thread-safe global measurement cache using an LRU (Least Recently Used) strategy.
233
+ * This ensures O(1) lookups while automatically discarding the oldest entries.
234
+ */
235
+ class MeasurementCache {
236
+ public:
237
+ struct CacheEntry {
238
+ MeasurementCacheKey key;
239
+ CachedSize size;
240
+ };
241
+
242
+ static MeasurementCache &shared()
243
+ {
244
+ static MeasurementCache instance;
245
+ return instance;
246
+ }
247
+
248
+ bool get(const MeasurementCacheKey &key, CachedSize &outSize)
249
+ {
250
+ std::lock_guard<std::mutex> lock(mutex_);
251
+
252
+ auto it = map_.find(key);
253
+ if (it == map_.end()) {
254
+ return false;
255
+ }
256
+
257
+ list_.splice(list_.begin(), list_, it->second);
258
+
259
+ outSize = it->second->size;
260
+ return true;
261
+ }
262
+
263
+ void set(const MeasurementCacheKey &key, CachedSize size)
264
+ {
265
+ std::lock_guard<std::mutex> lock(mutex_);
266
+
267
+ auto it = map_.find(key);
268
+ if (it != map_.end()) {
269
+ it->second->size = size;
270
+ list_.splice(list_.begin(), list_, it->second);
271
+ return;
272
+ }
273
+
274
+ list_.push_front({key, size});
275
+ map_[key] = list_.begin();
276
+
277
+ if (map_.size() > kMaxEntries) {
278
+ auto &lastEntry = list_.back();
279
+ map_.erase(lastEntry.key);
280
+ list_.pop_back();
281
+ }
282
+ }
283
+
284
+ void removeMatchingTiptap(const std::string &tiptap)
285
+ {
286
+ std::lock_guard<std::mutex> lock(mutex_);
287
+
288
+ for (auto it = list_.begin(); it != list_.end();) {
289
+ if (it->key.tiptap == tiptap) {
290
+ map_.erase(it->key);
291
+ it = list_.erase(it);
292
+ } else {
293
+ ++it;
294
+ }
295
+ }
296
+ }
297
+
298
+ private:
299
+ MeasurementCache() = default;
300
+
301
+ static constexpr size_t kMaxEntries = 512;
302
+ mutable std::mutex mutex_;
303
+
304
+ std::list<CacheEntry> list_;
305
+ std::unordered_map<MeasurementCacheKey, std::list<CacheEntry>::iterator, MeasurementCacheKeyHash> map_;
306
+ };
307
+
308
+ } // namespace facebook::react