@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,411 +1,411 @@
1
- package com.renderrichtext.styles
2
-
3
- import android.content.Context
4
- import android.content.res.AssetManager
5
- import android.graphics.Typeface
6
- import com.facebook.react.bridge.ReadableMap
7
- import com.facebook.react.common.ReactConstants
8
- import com.facebook.react.views.text.ReactTypefaceUtils.applyStyles
9
- import com.facebook.react.views.text.ReactTypefaceUtils.parseFontWeight
10
-
11
- /**
12
- * Main style configuration class that parses and caches all tiptap element styles.
13
- * Uses lazy initialization to defer parsing until styles are actually needed,
14
- * improving startup time for documents that don't use all tiptap features.
15
- */
16
- class StyleConfig(
17
- private val style: ReadableMap,
18
- context: Context,
19
- allowFontScaling: Boolean,
20
- maxFontSizeMultiplier: Float,
21
- ) {
22
- private val styleParser = StyleParser(context, allowFontScaling, maxFontSizeMultiplier)
23
- internal val assetManager: AssetManager = context.assets
24
- private val assets: AssetManager get() = assetManager
25
-
26
- private var paragraphStyleOverride: ParagraphStyle? = null
27
-
28
- val paragraphStyle: ParagraphStyle
29
- get() = paragraphStyleOverride ?: paragraphStyleDefault
30
-
31
- private val paragraphStyleDefault: ParagraphStyle by lazy {
32
- val map =
33
- requireNotNull(style.getMap("paragraph")) {
34
- "Paragraph style not found. JS should always provide defaults."
35
- }
36
- ParagraphStyle.fromReadableMap(map, styleParser)
37
- }
38
-
39
- /** Runs block with a temporary paragraph style override for table cell rendering. */
40
- fun <T> withParagraphOverride(
41
- override: ParagraphStyle,
42
- block: () -> T,
43
- ): T {
44
- paragraphStyleOverride = override
45
- try {
46
- return block()
47
- } finally {
48
- paragraphStyleOverride = null
49
- }
50
- }
51
-
52
- fun tableCellParagraphStyle(
53
- tableStyle: TableStyle,
54
- isHeader: Boolean,
55
- ): ParagraphStyle =
56
- paragraphStyleDefault.copy(
57
- fontSize = tableStyle.fontSize,
58
- fontFamily = if (isHeader && tableStyle.headerFontFamily.isNotEmpty()) tableStyle.headerFontFamily else tableStyle.fontFamily,
59
- fontWeight = if (isHeader) "bold" else tableStyle.fontWeight,
60
- color = if (isHeader) tableStyle.headerTextColor else tableStyle.color,
61
- lineHeight = tableStyle.lineHeight,
62
- marginTop = 0f,
63
- marginBottom = 0f,
64
- )
65
-
66
- val headingStyles: Array<HeadingStyle?> by lazy {
67
- Array(7) { index ->
68
- if (index == 0) {
69
- null
70
- } else {
71
- val levelKey = "h$index"
72
- val map =
73
- requireNotNull(style.getMap(levelKey)) {
74
- "Style for $levelKey not found. JS should always provide defaults."
75
- }
76
- HeadingStyle.fromReadableMap(map, styleParser)
77
- }
78
- }
79
- }
80
-
81
- // Cache typefaces for heading levels (1-6) - lazily initialized after headingStyles
82
- // Uses React Native's applyStyles to properly load custom fonts from assets
83
- val headingTypefaces: Array<Typeface?> by lazy {
84
- Array(7) { level ->
85
- if (level == 0) {
86
- null
87
- } else {
88
- val headingStyle = headingStyles[level]
89
- val fontFamily = headingStyle?.fontFamily?.takeIf { it.isNotEmpty() }
90
- val fontWeight = parseFontWeight(headingStyle?.fontWeight)
91
-
92
- if (fontFamily != null) {
93
- // Load the base font at NORMAL so the assets/fonts file resolves, then apply the
94
- // weight on the real typeface. Requesting the weight up front makes ReactFontManager
95
- // look for a `_bold` asset variant that single-file custom fonts lack and silently
96
- // fall back to a default system face. See SpanStyleCache.getTypeface.
97
- val base = applyStyles(null, ReactConstants.UNSET, ReactConstants.UNSET, fontFamily, assets)
98
- applyStyles(base, ReactConstants.UNSET, fontWeight, null, assets)
99
- } else {
100
- null
101
- }
102
- }
103
- }
104
- }
105
-
106
- val linkStyle: LinkStyle by lazy {
107
- val map =
108
- requireNotNull(style.getMap("link")) {
109
- "Link style not found. JS should always provide defaults."
110
- }
111
- LinkStyle.fromReadableMap(map, styleParser)
112
- }
113
-
114
- val linkVariants: List<LinkVariantEntry> by lazy {
115
- val array = style.getArray("linkVariants") ?: return@lazy emptyList()
116
- (0 until array.size()).mapNotNull { i ->
117
- array.getMap(i)?.let { LinkVariantEntry.fromReadableMap(it, styleParser) }
118
- }
119
- }
120
-
121
- /** Whether any variant can produce a pill; lets per-draw code skip pill lookups. */
122
- val hasLinkPills: Boolean by lazy { linkVariants.any { it.pill != null } }
123
-
124
- val strongStyle: StrongStyle by lazy {
125
- val map =
126
- requireNotNull(style.getMap("strong")) {
127
- "Strong style not found. JS should always provide defaults."
128
- }
129
- StrongStyle.fromReadableMap(map, styleParser)
130
- }
131
-
132
- val emphasisStyle: EmphasisStyle by lazy {
133
- val map =
134
- requireNotNull(style.getMap("em")) {
135
- "Emphasis style not found. JS should always provide defaults."
136
- }
137
- EmphasisStyle.fromReadableMap(map, styleParser)
138
- }
139
-
140
- val strikethroughStyle: StrikethroughStyle by lazy {
141
- val map =
142
- requireNotNull(style.getMap("strikethrough")) {
143
- "Strikethrough style not found. JS should always provide defaults."
144
- }
145
- StrikethroughStyle.fromReadableMap(map, styleParser)
146
- }
147
-
148
- val underlineStyle: UnderlineStyle by lazy {
149
- val map =
150
- requireNotNull(style.getMap("underline")) {
151
- "Underline style not found. JS should always provide defaults."
152
- }
153
- UnderlineStyle.fromReadableMap(map, styleParser)
154
- }
155
-
156
- val codeStyle: CodeStyle by lazy {
157
- val map =
158
- requireNotNull(style.getMap("code")) {
159
- "Code style not found. JS should always provide defaults."
160
- }
161
- CodeStyle.fromReadableMap(map, styleParser)
162
- }
163
-
164
- val mentionStyle: MentionStyle by lazy {
165
- val map =
166
- requireNotNull(style.getMap("mention")) {
167
- "Mention style not found. JS should always provide defaults."
168
- }
169
- MentionStyle.fromReadableMap(map, styleParser)
170
- }
171
-
172
- val factoidStyle: FactoidStyle by lazy {
173
- val map =
174
- requireNotNull(style.getMap("factoid")) {
175
- "Factoid style not found. JS should always provide defaults."
176
- }
177
- FactoidStyle.fromReadableMap(map, styleParser)
178
- }
179
-
180
- val imageStyle: ImageStyle by lazy {
181
- val map =
182
- requireNotNull(style.getMap("image")) {
183
- "Image style not found. JS should always provide defaults."
184
- }
185
- ImageStyle.fromReadableMap(map, styleParser)
186
- }
187
-
188
- var imageRequestHeaders: Map<String, String> = emptyMap()
189
-
190
- /** Per-link pill content keyed by exact URL; content, so it lives outside the style map. */
191
- var linkPillContent: Map<String, LinkPillContent> = emptyMap()
192
-
193
- val videoStyle: VideoStyle by lazy {
194
- val map =
195
- requireNotNull(style.getMap("video")) {
196
- "Video style not found. JS should always provide defaults."
197
- }
198
- VideoStyle.fromReadableMap(map, styleParser)
199
- }
200
-
201
- val inlineImageStyle: InlineImageStyle by lazy {
202
- val map =
203
- requireNotNull(style.getMap("inlineImage")) {
204
- "InlineImage style not found. JS should always provide defaults."
205
- }
206
- InlineImageStyle.fromReadableMap(map, styleParser)
207
- }
208
-
209
- val blockquoteStyle: BlockquoteStyle by lazy {
210
- val map =
211
- requireNotNull(style.getMap("blockquote")) {
212
- "Blockquote style not found. JS should always provide defaults."
213
- }
214
- BlockquoteStyle.fromReadableMap(map, styleParser)
215
- }
216
-
217
- val listStyle: ListStyle by lazy {
218
- val map =
219
- requireNotNull(style.getMap("list")) {
220
- "List style not found. JS should always provide defaults."
221
- }
222
- ListStyle.fromReadableMap(map, styleParser)
223
- }
224
-
225
- val codeBlockStyle: CodeBlockStyle by lazy {
226
- val map =
227
- requireNotNull(style.getMap("codeBlock")) {
228
- "CodeBlock style not found. JS should always provide defaults."
229
- }
230
- CodeBlockStyle.fromReadableMap(map, styleParser)
231
- }
232
-
233
- val thematicBreakStyle: ThematicBreakStyle by lazy {
234
- val map =
235
- requireNotNull(style.getMap("thematicBreak")) {
236
- "ThematicBreak style not found. JS should always provide defaults."
237
- }
238
- ThematicBreakStyle.fromReadableMap(map, styleParser)
239
- }
240
-
241
- val tableStyle: TableStyle by lazy {
242
- val map =
243
- requireNotNull(style.getMap("table")) {
244
- "Table style not found. JS should always provide defaults."
245
- }
246
- TableStyle.fromReadableMap(map, styleParser)
247
- }
248
-
249
- val taskListStyle: TaskListStyle by lazy {
250
- val map =
251
- requireNotNull(style.getMap("taskList")) {
252
- "TaskList style not found. JS should always provide defaults."
253
- }
254
- TaskListStyle.fromReadableMap(map, styleParser)
255
- }
256
-
257
- val mathStyle: MathStyle by lazy {
258
- val map =
259
- requireNotNull(style.getMap("math")) {
260
- "Math style not found. JS should always provide defaults."
261
- }
262
- MathStyle.fromReadableMap(map, styleParser)
263
- }
264
-
265
- val inlineMathStyle: InlineMathStyle by lazy {
266
- val map =
267
- requireNotNull(style.getMap("inlineMath")) {
268
- "InlineMath style not found. JS should always provide defaults."
269
- }
270
- InlineMathStyle.fromReadableMap(map, styleParser)
271
- }
272
-
273
- val spoilerStyle: SpoilerStyle by lazy {
274
- val map =
275
- requireNotNull(style.getMap("spoiler")) {
276
- "Spoiler style not found. JS should always provide defaults."
277
- }
278
- SpoilerStyle.fromReadableMap(map, styleParser)
279
- }
280
-
281
- val superscriptStyle: SuperscriptStyle by lazy {
282
- val map =
283
- requireNotNull(style.getMap("superscript")) {
284
- "Superscript style not found. JS should always provide defaults."
285
- }
286
- SuperscriptStyle.fromReadableMap(map)
287
- }
288
-
289
- val subscriptStyle: SubscriptStyle by lazy {
290
- val map =
291
- requireNotNull(style.getMap("subscript")) {
292
- "Subscript style not found. JS should always provide defaults."
293
- }
294
- SubscriptStyle.fromReadableMap(map)
295
- }
296
-
297
- val highlightStyle: HighlightStyle by lazy {
298
- val map =
299
- requireNotNull(style.getMap("highlight")) {
300
- "Highlight style not found. JS should always provide defaults."
301
- }
302
- HighlightStyle.fromReadableMap(map, styleParser)
303
- }
304
-
305
- val tableTypeface: Typeface? by lazy {
306
- val fontFamily = tableStyle.fontFamily.takeIf { it.isNotEmpty() }
307
- val fontWeight = parseFontWeight(tableStyle.fontWeight)
308
- if (fontFamily != null) {
309
- applyStyles(null, ReactConstants.UNSET, fontWeight, fontFamily, assets)
310
- } else {
311
- null
312
- }
313
- }
314
-
315
- val tableHeaderTypeface: Typeface? by lazy {
316
- val headerFamily = tableStyle.headerFontFamily.takeIf { it.isNotEmpty() }
317
- val baseFamily = tableStyle.fontFamily.takeIf { it.isNotEmpty() }
318
-
319
- when {
320
- // 1. Try Header font (specific variant)
321
- headerFamily != null -> {
322
- applyStyles(null, ReactConstants.UNSET, parseFontWeight("normal"), headerFamily, assets)
323
- }
324
-
325
- // 2. Try Table font (forced to bold)
326
- baseFamily != null -> {
327
- applyStyles(null, ReactConstants.UNSET, parseFontWeight("bold"), baseFamily, assets)
328
- }
329
-
330
- // 3. System Fallback
331
- else -> {
332
- Typeface.DEFAULT_BOLD
333
- }
334
- }
335
- }
336
-
337
- /**
338
- * Returns true if any paragraph or heading style uses justify alignment.
339
- * Used to enable justification mode on the TextView (API 26+).
340
- */
341
- val needsJustify: Boolean by lazy {
342
- paragraphStyle.textAlign.needsJustify ||
343
- headingStyles.filterNotNull().any { it.textAlign.needsJustify }
344
- }
345
-
346
- override fun equals(other: Any?): Boolean {
347
- if (this === other) return true
348
- if (other !is StyleConfig) return false
349
-
350
- return paragraphStyle == other.paragraphStyle &&
351
- headingStyles.contentEquals(other.headingStyles) &&
352
- linkStyle == other.linkStyle &&
353
- linkVariants == other.linkVariants &&
354
- strongStyle == other.strongStyle &&
355
- emphasisStyle == other.emphasisStyle &&
356
- strikethroughStyle == other.strikethroughStyle &&
357
- underlineStyle == other.underlineStyle &&
358
- codeStyle == other.codeStyle &&
359
- mentionStyle == other.mentionStyle &&
360
- factoidStyle == other.factoidStyle &&
361
- imageStyle == other.imageStyle &&
362
- videoStyle == other.videoStyle &&
363
- inlineImageStyle == other.inlineImageStyle &&
364
- blockquoteStyle == other.blockquoteStyle &&
365
- listStyle == other.listStyle &&
366
- codeBlockStyle == other.codeBlockStyle &&
367
- thematicBreakStyle == other.thematicBreakStyle &&
368
- tableStyle == other.tableStyle &&
369
- taskListStyle == other.taskListStyle &&
370
- mathStyle == other.mathStyle &&
371
- inlineMathStyle == other.inlineMathStyle &&
372
- spoilerStyle == other.spoilerStyle &&
373
- superscriptStyle == other.superscriptStyle &&
374
- subscriptStyle == other.subscriptStyle &&
375
- highlightStyle == other.highlightStyle &&
376
- imageRequestHeaders == other.imageRequestHeaders &&
377
- linkPillContent == other.linkPillContent
378
- }
379
-
380
- override fun hashCode(): Int {
381
- var result = paragraphStyle.hashCode()
382
- result = 31 * result + headingStyles.contentHashCode()
383
- result = 31 * result + linkStyle.hashCode()
384
- result = 31 * result + linkVariants.hashCode()
385
- result = 31 * result + strongStyle.hashCode()
386
- result = 31 * result + emphasisStyle.hashCode()
387
- result = 31 * result + strikethroughStyle.hashCode()
388
- result = 31 * result + underlineStyle.hashCode()
389
- result = 31 * result + codeStyle.hashCode()
390
- result = 31 * result + mentionStyle.hashCode()
391
- result = 31 * result + factoidStyle.hashCode()
392
- result = 31 * result + imageStyle.hashCode()
393
- result = 31 * result + videoStyle.hashCode()
394
- result = 31 * result + inlineImageStyle.hashCode()
395
- result = 31 * result + blockquoteStyle.hashCode()
396
- result = 31 * result + listStyle.hashCode()
397
- result = 31 * result + codeBlockStyle.hashCode()
398
- result = 31 * result + thematicBreakStyle.hashCode()
399
- result = 31 * result + tableStyle.hashCode()
400
- result = 31 * result + taskListStyle.hashCode()
401
- result = 31 * result + mathStyle.hashCode()
402
- result = 31 * result + inlineMathStyle.hashCode()
403
- result = 31 * result + spoilerStyle.hashCode()
404
- result = 31 * result + superscriptStyle.hashCode()
405
- result = 31 * result + subscriptStyle.hashCode()
406
- result = 31 * result + highlightStyle.hashCode()
407
- result = 31 * result + imageRequestHeaders.hashCode()
408
- result = 31 * result + linkPillContent.hashCode()
409
- return result
410
- }
411
- }
1
+ package com.renderrichtext.styles
2
+
3
+ import android.content.Context
4
+ import android.content.res.AssetManager
5
+ import android.graphics.Typeface
6
+ import com.facebook.react.bridge.ReadableMap
7
+ import com.facebook.react.common.ReactConstants
8
+ import com.facebook.react.views.text.ReactTypefaceUtils.applyStyles
9
+ import com.facebook.react.views.text.ReactTypefaceUtils.parseFontWeight
10
+
11
+ /**
12
+ * Main style configuration class that parses and caches all tiptap element styles.
13
+ * Uses lazy initialization to defer parsing until styles are actually needed,
14
+ * improving startup time for documents that don't use all tiptap features.
15
+ */
16
+ class StyleConfig(
17
+ private val style: ReadableMap,
18
+ context: Context,
19
+ allowFontScaling: Boolean,
20
+ maxFontSizeMultiplier: Float,
21
+ ) {
22
+ private val styleParser = StyleParser(context, allowFontScaling, maxFontSizeMultiplier)
23
+ internal val assetManager: AssetManager = context.assets
24
+ private val assets: AssetManager get() = assetManager
25
+
26
+ private var paragraphStyleOverride: ParagraphStyle? = null
27
+
28
+ val paragraphStyle: ParagraphStyle
29
+ get() = paragraphStyleOverride ?: paragraphStyleDefault
30
+
31
+ private val paragraphStyleDefault: ParagraphStyle by lazy {
32
+ val map =
33
+ requireNotNull(style.getMap("paragraph")) {
34
+ "Paragraph style not found. JS should always provide defaults."
35
+ }
36
+ ParagraphStyle.fromReadableMap(map, styleParser)
37
+ }
38
+
39
+ /** Runs block with a temporary paragraph style override for table cell rendering. */
40
+ fun <T> withParagraphOverride(
41
+ override: ParagraphStyle,
42
+ block: () -> T,
43
+ ): T {
44
+ paragraphStyleOverride = override
45
+ try {
46
+ return block()
47
+ } finally {
48
+ paragraphStyleOverride = null
49
+ }
50
+ }
51
+
52
+ fun tableCellParagraphStyle(
53
+ tableStyle: TableStyle,
54
+ isHeader: Boolean,
55
+ ): ParagraphStyle =
56
+ paragraphStyleDefault.copy(
57
+ fontSize = tableStyle.fontSize,
58
+ fontFamily = if (isHeader && tableStyle.headerFontFamily.isNotEmpty()) tableStyle.headerFontFamily else tableStyle.fontFamily,
59
+ fontWeight = if (isHeader) "bold" else tableStyle.fontWeight,
60
+ color = if (isHeader) tableStyle.headerTextColor else tableStyle.color,
61
+ lineHeight = tableStyle.lineHeight,
62
+ marginTop = 0f,
63
+ marginBottom = 0f,
64
+ )
65
+
66
+ val headingStyles: Array<HeadingStyle?> by lazy {
67
+ Array(7) { index ->
68
+ if (index == 0) {
69
+ null
70
+ } else {
71
+ val levelKey = "h$index"
72
+ val map =
73
+ requireNotNull(style.getMap(levelKey)) {
74
+ "Style for $levelKey not found. JS should always provide defaults."
75
+ }
76
+ HeadingStyle.fromReadableMap(map, styleParser)
77
+ }
78
+ }
79
+ }
80
+
81
+ // Cache typefaces for heading levels (1-6) - lazily initialized after headingStyles
82
+ // Uses React Native's applyStyles to properly load custom fonts from assets
83
+ val headingTypefaces: Array<Typeface?> by lazy {
84
+ Array(7) { level ->
85
+ if (level == 0) {
86
+ null
87
+ } else {
88
+ val headingStyle = headingStyles[level]
89
+ val fontFamily = headingStyle?.fontFamily?.takeIf { it.isNotEmpty() }
90
+ val fontWeight = parseFontWeight(headingStyle?.fontWeight)
91
+
92
+ if (fontFamily != null) {
93
+ // Load the base font at NORMAL so the assets/fonts file resolves, then apply the
94
+ // weight on the real typeface. Requesting the weight up front makes ReactFontManager
95
+ // look for a `_bold` asset variant that single-file custom fonts lack and silently
96
+ // fall back to a default system face. See SpanStyleCache.getTypeface.
97
+ val base = applyStyles(null, ReactConstants.UNSET, ReactConstants.UNSET, fontFamily, assets)
98
+ applyStyles(base, ReactConstants.UNSET, fontWeight, null, assets)
99
+ } else {
100
+ null
101
+ }
102
+ }
103
+ }
104
+ }
105
+
106
+ val linkStyle: LinkStyle by lazy {
107
+ val map =
108
+ requireNotNull(style.getMap("link")) {
109
+ "Link style not found. JS should always provide defaults."
110
+ }
111
+ LinkStyle.fromReadableMap(map, styleParser)
112
+ }
113
+
114
+ val linkVariants: List<LinkVariantEntry> by lazy {
115
+ val array = style.getArray("linkVariants") ?: return@lazy emptyList()
116
+ (0 until array.size()).mapNotNull { i ->
117
+ array.getMap(i)?.let { LinkVariantEntry.fromReadableMap(it, styleParser) }
118
+ }
119
+ }
120
+
121
+ /** Whether any variant can produce a pill; lets per-draw code skip pill lookups. */
122
+ val hasLinkPills: Boolean by lazy { linkVariants.any { it.pill != null } }
123
+
124
+ val strongStyle: StrongStyle by lazy {
125
+ val map =
126
+ requireNotNull(style.getMap("strong")) {
127
+ "Strong style not found. JS should always provide defaults."
128
+ }
129
+ StrongStyle.fromReadableMap(map, styleParser)
130
+ }
131
+
132
+ val emphasisStyle: EmphasisStyle by lazy {
133
+ val map =
134
+ requireNotNull(style.getMap("em")) {
135
+ "Emphasis style not found. JS should always provide defaults."
136
+ }
137
+ EmphasisStyle.fromReadableMap(map, styleParser)
138
+ }
139
+
140
+ val strikethroughStyle: StrikethroughStyle by lazy {
141
+ val map =
142
+ requireNotNull(style.getMap("strikethrough")) {
143
+ "Strikethrough style not found. JS should always provide defaults."
144
+ }
145
+ StrikethroughStyle.fromReadableMap(map, styleParser)
146
+ }
147
+
148
+ val underlineStyle: UnderlineStyle by lazy {
149
+ val map =
150
+ requireNotNull(style.getMap("underline")) {
151
+ "Underline style not found. JS should always provide defaults."
152
+ }
153
+ UnderlineStyle.fromReadableMap(map, styleParser)
154
+ }
155
+
156
+ val codeStyle: CodeStyle by lazy {
157
+ val map =
158
+ requireNotNull(style.getMap("code")) {
159
+ "Code style not found. JS should always provide defaults."
160
+ }
161
+ CodeStyle.fromReadableMap(map, styleParser)
162
+ }
163
+
164
+ val mentionStyle: MentionStyle by lazy {
165
+ val map =
166
+ requireNotNull(style.getMap("mention")) {
167
+ "Mention style not found. JS should always provide defaults."
168
+ }
169
+ MentionStyle.fromReadableMap(map, styleParser)
170
+ }
171
+
172
+ val factoidStyle: FactoidStyle by lazy {
173
+ val map =
174
+ requireNotNull(style.getMap("factoid")) {
175
+ "Factoid style not found. JS should always provide defaults."
176
+ }
177
+ FactoidStyle.fromReadableMap(map, styleParser)
178
+ }
179
+
180
+ val imageStyle: ImageStyle by lazy {
181
+ val map =
182
+ requireNotNull(style.getMap("image")) {
183
+ "Image style not found. JS should always provide defaults."
184
+ }
185
+ ImageStyle.fromReadableMap(map, styleParser)
186
+ }
187
+
188
+ var imageRequestHeaders: Map<String, String> = emptyMap()
189
+
190
+ /** Per-link pill content keyed by exact URL; content, so it lives outside the style map. */
191
+ var linkPillContent: Map<String, LinkPillContent> = emptyMap()
192
+
193
+ val videoStyle: VideoStyle by lazy {
194
+ val map =
195
+ requireNotNull(style.getMap("video")) {
196
+ "Video style not found. JS should always provide defaults."
197
+ }
198
+ VideoStyle.fromReadableMap(map, styleParser)
199
+ }
200
+
201
+ val inlineImageStyle: InlineImageStyle by lazy {
202
+ val map =
203
+ requireNotNull(style.getMap("inlineImage")) {
204
+ "InlineImage style not found. JS should always provide defaults."
205
+ }
206
+ InlineImageStyle.fromReadableMap(map, styleParser)
207
+ }
208
+
209
+ val blockquoteStyle: BlockquoteStyle by lazy {
210
+ val map =
211
+ requireNotNull(style.getMap("blockquote")) {
212
+ "Blockquote style not found. JS should always provide defaults."
213
+ }
214
+ BlockquoteStyle.fromReadableMap(map, styleParser)
215
+ }
216
+
217
+ val listStyle: ListStyle by lazy {
218
+ val map =
219
+ requireNotNull(style.getMap("list")) {
220
+ "List style not found. JS should always provide defaults."
221
+ }
222
+ ListStyle.fromReadableMap(map, styleParser)
223
+ }
224
+
225
+ val codeBlockStyle: CodeBlockStyle by lazy {
226
+ val map =
227
+ requireNotNull(style.getMap("codeBlock")) {
228
+ "CodeBlock style not found. JS should always provide defaults."
229
+ }
230
+ CodeBlockStyle.fromReadableMap(map, styleParser)
231
+ }
232
+
233
+ val thematicBreakStyle: ThematicBreakStyle by lazy {
234
+ val map =
235
+ requireNotNull(style.getMap("thematicBreak")) {
236
+ "ThematicBreak style not found. JS should always provide defaults."
237
+ }
238
+ ThematicBreakStyle.fromReadableMap(map, styleParser)
239
+ }
240
+
241
+ val tableStyle: TableStyle by lazy {
242
+ val map =
243
+ requireNotNull(style.getMap("table")) {
244
+ "Table style not found. JS should always provide defaults."
245
+ }
246
+ TableStyle.fromReadableMap(map, styleParser)
247
+ }
248
+
249
+ val taskListStyle: TaskListStyle by lazy {
250
+ val map =
251
+ requireNotNull(style.getMap("taskList")) {
252
+ "TaskList style not found. JS should always provide defaults."
253
+ }
254
+ TaskListStyle.fromReadableMap(map, styleParser)
255
+ }
256
+
257
+ val mathStyle: MathStyle by lazy {
258
+ val map =
259
+ requireNotNull(style.getMap("math")) {
260
+ "Math style not found. JS should always provide defaults."
261
+ }
262
+ MathStyle.fromReadableMap(map, styleParser)
263
+ }
264
+
265
+ val inlineMathStyle: InlineMathStyle by lazy {
266
+ val map =
267
+ requireNotNull(style.getMap("inlineMath")) {
268
+ "InlineMath style not found. JS should always provide defaults."
269
+ }
270
+ InlineMathStyle.fromReadableMap(map, styleParser)
271
+ }
272
+
273
+ val spoilerStyle: SpoilerStyle by lazy {
274
+ val map =
275
+ requireNotNull(style.getMap("spoiler")) {
276
+ "Spoiler style not found. JS should always provide defaults."
277
+ }
278
+ SpoilerStyle.fromReadableMap(map, styleParser)
279
+ }
280
+
281
+ val superscriptStyle: SuperscriptStyle by lazy {
282
+ val map =
283
+ requireNotNull(style.getMap("superscript")) {
284
+ "Superscript style not found. JS should always provide defaults."
285
+ }
286
+ SuperscriptStyle.fromReadableMap(map)
287
+ }
288
+
289
+ val subscriptStyle: SubscriptStyle by lazy {
290
+ val map =
291
+ requireNotNull(style.getMap("subscript")) {
292
+ "Subscript style not found. JS should always provide defaults."
293
+ }
294
+ SubscriptStyle.fromReadableMap(map)
295
+ }
296
+
297
+ val highlightStyle: HighlightStyle by lazy {
298
+ val map =
299
+ requireNotNull(style.getMap("highlight")) {
300
+ "Highlight style not found. JS should always provide defaults."
301
+ }
302
+ HighlightStyle.fromReadableMap(map, styleParser)
303
+ }
304
+
305
+ val tableTypeface: Typeface? by lazy {
306
+ val fontFamily = tableStyle.fontFamily.takeIf { it.isNotEmpty() }
307
+ val fontWeight = parseFontWeight(tableStyle.fontWeight)
308
+ if (fontFamily != null) {
309
+ applyStyles(null, ReactConstants.UNSET, fontWeight, fontFamily, assets)
310
+ } else {
311
+ null
312
+ }
313
+ }
314
+
315
+ val tableHeaderTypeface: Typeface? by lazy {
316
+ val headerFamily = tableStyle.headerFontFamily.takeIf { it.isNotEmpty() }
317
+ val baseFamily = tableStyle.fontFamily.takeIf { it.isNotEmpty() }
318
+
319
+ when {
320
+ // 1. Try Header font (specific variant)
321
+ headerFamily != null -> {
322
+ applyStyles(null, ReactConstants.UNSET, parseFontWeight("normal"), headerFamily, assets)
323
+ }
324
+
325
+ // 2. Try Table font (forced to bold)
326
+ baseFamily != null -> {
327
+ applyStyles(null, ReactConstants.UNSET, parseFontWeight("bold"), baseFamily, assets)
328
+ }
329
+
330
+ // 3. System Fallback
331
+ else -> {
332
+ Typeface.DEFAULT_BOLD
333
+ }
334
+ }
335
+ }
336
+
337
+ /**
338
+ * Returns true if any paragraph or heading style uses justify alignment.
339
+ * Used to enable justification mode on the TextView (API 26+).
340
+ */
341
+ val needsJustify: Boolean by lazy {
342
+ paragraphStyle.textAlign.needsJustify ||
343
+ headingStyles.filterNotNull().any { it.textAlign.needsJustify }
344
+ }
345
+
346
+ override fun equals(other: Any?): Boolean {
347
+ if (this === other) return true
348
+ if (other !is StyleConfig) return false
349
+
350
+ return paragraphStyle == other.paragraphStyle &&
351
+ headingStyles.contentEquals(other.headingStyles) &&
352
+ linkStyle == other.linkStyle &&
353
+ linkVariants == other.linkVariants &&
354
+ strongStyle == other.strongStyle &&
355
+ emphasisStyle == other.emphasisStyle &&
356
+ strikethroughStyle == other.strikethroughStyle &&
357
+ underlineStyle == other.underlineStyle &&
358
+ codeStyle == other.codeStyle &&
359
+ mentionStyle == other.mentionStyle &&
360
+ factoidStyle == other.factoidStyle &&
361
+ imageStyle == other.imageStyle &&
362
+ videoStyle == other.videoStyle &&
363
+ inlineImageStyle == other.inlineImageStyle &&
364
+ blockquoteStyle == other.blockquoteStyle &&
365
+ listStyle == other.listStyle &&
366
+ codeBlockStyle == other.codeBlockStyle &&
367
+ thematicBreakStyle == other.thematicBreakStyle &&
368
+ tableStyle == other.tableStyle &&
369
+ taskListStyle == other.taskListStyle &&
370
+ mathStyle == other.mathStyle &&
371
+ inlineMathStyle == other.inlineMathStyle &&
372
+ spoilerStyle == other.spoilerStyle &&
373
+ superscriptStyle == other.superscriptStyle &&
374
+ subscriptStyle == other.subscriptStyle &&
375
+ highlightStyle == other.highlightStyle &&
376
+ imageRequestHeaders == other.imageRequestHeaders &&
377
+ linkPillContent == other.linkPillContent
378
+ }
379
+
380
+ override fun hashCode(): Int {
381
+ var result = paragraphStyle.hashCode()
382
+ result = 31 * result + headingStyles.contentHashCode()
383
+ result = 31 * result + linkStyle.hashCode()
384
+ result = 31 * result + linkVariants.hashCode()
385
+ result = 31 * result + strongStyle.hashCode()
386
+ result = 31 * result + emphasisStyle.hashCode()
387
+ result = 31 * result + strikethroughStyle.hashCode()
388
+ result = 31 * result + underlineStyle.hashCode()
389
+ result = 31 * result + codeStyle.hashCode()
390
+ result = 31 * result + mentionStyle.hashCode()
391
+ result = 31 * result + factoidStyle.hashCode()
392
+ result = 31 * result + imageStyle.hashCode()
393
+ result = 31 * result + videoStyle.hashCode()
394
+ result = 31 * result + inlineImageStyle.hashCode()
395
+ result = 31 * result + blockquoteStyle.hashCode()
396
+ result = 31 * result + listStyle.hashCode()
397
+ result = 31 * result + codeBlockStyle.hashCode()
398
+ result = 31 * result + thematicBreakStyle.hashCode()
399
+ result = 31 * result + tableStyle.hashCode()
400
+ result = 31 * result + taskListStyle.hashCode()
401
+ result = 31 * result + mathStyle.hashCode()
402
+ result = 31 * result + inlineMathStyle.hashCode()
403
+ result = 31 * result + spoilerStyle.hashCode()
404
+ result = 31 * result + superscriptStyle.hashCode()
405
+ result = 31 * result + subscriptStyle.hashCode()
406
+ result = 31 * result + highlightStyle.hashCode()
407
+ result = 31 * result + imageRequestHeaders.hashCode()
408
+ result = 31 * result + linkPillContent.hashCode()
409
+ return result
410
+ }
411
+ }