react-native-enriched-markdown-scaffold 0.7.4-scaffold.9 → 1.0.2-scaffold.10

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 (505) hide show
  1. package/README.md +54 -8
  2. package/ReactNativeEnrichedMarkdown.podspec +82 -73
  3. package/android/build.gradle +188 -1
  4. package/android/consumer-rules.pro +1 -1
  5. package/android/generated/java/com/facebook/react/viewmanagers/EnrichedMarkdownManagerDelegate.java +27 -0
  6. package/android/generated/java/com/facebook/react/viewmanagers/EnrichedMarkdownManagerInterface.java +7 -0
  7. package/android/generated/java/com/facebook/react/viewmanagers/EnrichedMarkdownTextInputManagerDelegate.java +24 -0
  8. package/android/generated/java/com/facebook/react/viewmanagers/EnrichedMarkdownTextInputManagerInterface.java +8 -0
  9. package/android/generated/java/com/facebook/react/viewmanagers/EnrichedMarkdownTextManagerDelegate.java +27 -0
  10. package/android/generated/java/com/facebook/react/viewmanagers/EnrichedMarkdownTextManagerInterface.java +7 -0
  11. package/android/generated/jni/react/renderer/components/EnrichedMarkdownTextSpec/EventEmitters.cpp +223 -0
  12. package/android/generated/jni/react/renderer/components/EnrichedMarkdownTextSpec/EventEmitters.h +183 -0
  13. package/android/generated/jni/react/renderer/components/EnrichedMarkdownTextSpec/Props.cpp +65 -0
  14. package/android/generated/jni/react/renderer/components/EnrichedMarkdownTextSpec/Props.h +1086 -61
  15. package/android/src/main/baseline-prof.txt +1 -1
  16. package/android/src/main/cpp/jni-adapter.cpp +74 -0
  17. package/android/src/main/java/com/swmansion/enriched/markdown/EnrichedMarkdown.kt +351 -13
  18. package/android/src/main/java/com/swmansion/enriched/markdown/EnrichedMarkdownInternalText.kt +62 -0
  19. package/android/src/main/java/com/swmansion/enriched/markdown/EnrichedMarkdownManager.kt +85 -0
  20. package/android/src/main/java/com/swmansion/enriched/markdown/EnrichedMarkdownText.kt +160 -1
  21. package/android/src/main/java/com/swmansion/enriched/markdown/EnrichedMarkdownTextLayoutManager.kt +10 -1
  22. package/android/src/main/java/com/swmansion/enriched/markdown/EnrichedMarkdownTextManager.kt +76 -0
  23. package/android/src/main/java/com/swmansion/enriched/markdown/MeasurementStore.kt +126 -10
  24. package/android/src/main/java/com/swmansion/enriched/markdown/events/CopyPressEvent.kt +24 -0
  25. package/android/src/main/java/com/swmansion/enriched/markdown/events/CopyRequestEvent.kt +28 -0
  26. package/android/src/main/java/com/swmansion/enriched/markdown/events/LinkLayoutEvent.kt +36 -0
  27. package/android/src/main/java/com/swmansion/enriched/markdown/events/SelectionChangeEvent.kt +43 -0
  28. package/android/src/main/java/com/swmansion/enriched/markdown/input/EnrichedMarkdownTextInputManager.kt +54 -4
  29. package/android/src/main/java/com/swmansion/enriched/markdown/input/EnrichedMarkdownTextInputView.kt +923 -462
  30. package/android/src/main/java/com/swmansion/enriched/markdown/input/MarkdownClipboard.kt +42 -0
  31. package/android/src/main/java/com/swmansion/enriched/markdown/input/editing/BlockEditCoordinator.kt +196 -0
  32. package/android/src/main/java/com/swmansion/enriched/markdown/input/editing/ClipboardCoordinator.kt +73 -0
  33. package/android/src/main/java/com/swmansion/enriched/markdown/input/editing/EditContext.kt +19 -0
  34. package/android/src/main/java/com/swmansion/enriched/markdown/input/editing/EditPipeline.kt +248 -0
  35. package/android/src/main/java/com/swmansion/enriched/markdown/input/editing/EditSession.kt +52 -0
  36. package/android/src/main/java/com/swmansion/enriched/markdown/input/editing/InputConnectionWrapper.kt +108 -7
  37. package/android/src/main/java/com/swmansion/enriched/markdown/input/editing/LinkCoordinator.kt +69 -0
  38. package/android/src/main/java/com/swmansion/enriched/markdown/input/editing/MarkdownTextWatcher.kt +3 -3
  39. package/android/src/main/java/com/swmansion/enriched/markdown/input/editing/MentionCoordinator.kt +118 -0
  40. package/android/src/main/java/com/swmansion/enriched/markdown/input/events/OnChangeStateEvent.kt +26 -0
  41. package/android/src/main/java/com/swmansion/enriched/markdown/input/events/OnContextMenuItemPressEvent.kt +26 -0
  42. package/android/src/main/java/com/swmansion/enriched/markdown/input/events/OnInputKeyPressEvent.kt +24 -0
  43. package/android/src/main/java/com/swmansion/enriched/markdown/input/events/OnPasteEvent.kt +24 -0
  44. package/android/src/main/java/com/swmansion/enriched/markdown/input/formatting/BlockStore.kt +254 -0
  45. package/android/src/main/java/com/swmansion/enriched/markdown/input/formatting/FormattingStore.kt +80 -87
  46. package/android/src/main/java/com/swmansion/enriched/markdown/input/formatting/InputFormatter.kt +109 -1
  47. package/android/src/main/java/com/swmansion/enriched/markdown/input/formatting/InputParser.kt +116 -22
  48. package/android/src/main/java/com/swmansion/enriched/markdown/input/formatting/MarkdownSerializer.kt +167 -38
  49. package/android/src/main/java/com/swmansion/enriched/markdown/input/formatting/RangeEditAdjustment.kt +149 -0
  50. package/android/src/main/java/com/swmansion/enriched/markdown/input/layout/InputEventEmitter.kt +66 -5
  51. package/android/src/main/java/com/swmansion/enriched/markdown/input/layout/InputMeasurementStore.kt +4 -2
  52. package/android/src/main/java/com/swmansion/enriched/markdown/input/model/BlockRange.kt +27 -0
  53. package/android/src/main/java/com/swmansion/enriched/markdown/input/model/BlockType.kt +48 -0
  54. package/android/src/main/java/com/swmansion/enriched/markdown/input/model/FormattingRange.kt +9 -4
  55. package/android/src/main/java/com/swmansion/enriched/markdown/input/model/InputFormatterStyle.kt +39 -2
  56. package/android/src/main/java/com/swmansion/enriched/markdown/input/model/MathAtom.kt +20 -0
  57. package/android/src/main/java/com/swmansion/enriched/markdown/input/model/MathChipStyle.kt +1 -1
  58. package/android/src/main/java/com/swmansion/enriched/markdown/input/model/MutableRangeBounds.kt +11 -0
  59. package/android/src/main/java/com/swmansion/enriched/markdown/input/spans/InputBulletSpan.kt +82 -0
  60. package/android/src/main/java/com/swmansion/enriched/markdown/input/spans/InputHeadingSpan.kt +58 -0
  61. package/android/src/main/java/com/swmansion/enriched/markdown/input/spans/InputListItemSpacingSpan.kt +37 -0
  62. package/android/src/main/java/com/swmansion/enriched/markdown/input/spans/InputOrderedListMarkerSpan.kt +63 -0
  63. package/android/src/main/java/com/swmansion/enriched/markdown/input/styles/BlockHandler.kt +54 -0
  64. package/android/src/main/java/com/swmansion/enriched/markdown/input/styles/HeadingBlockHandler.kt +27 -0
  65. package/android/src/main/java/com/swmansion/enriched/markdown/input/styles/OrderedListBlockHandler.kt +38 -0
  66. package/android/src/main/java/com/swmansion/enriched/markdown/input/styles/UnorderedListBlockHandler.kt +37 -0
  67. package/android/src/main/java/com/swmansion/enriched/markdown/input/toolbar/InputContextMenu.kt +8 -26
  68. package/android/src/main/java/com/swmansion/enriched/markdown/parser/MarkdownASTNode.kt +1 -0
  69. package/android/src/main/java/com/swmansion/enriched/markdown/parser/Parser.kt +1 -0
  70. package/android/src/main/java/com/swmansion/enriched/markdown/renderer/BlockStyleContext.kt +9 -2
  71. package/android/src/main/java/com/swmansion/enriched/markdown/renderer/BlockquoteRenderer.kt +100 -12
  72. package/android/src/main/java/com/swmansion/enriched/markdown/renderer/CodeBlockRenderer.kt +16 -1
  73. package/android/src/main/java/com/swmansion/enriched/markdown/renderer/HeadingRenderer.kt +4 -0
  74. package/android/src/main/java/com/swmansion/enriched/markdown/renderer/LinkRenderer.kt +37 -7
  75. package/android/src/main/java/com/swmansion/enriched/markdown/renderer/ListContextManager.kt +2 -1
  76. package/android/src/main/java/com/swmansion/enriched/markdown/renderer/ListItemRenderer.kt +74 -18
  77. package/android/src/main/java/com/swmansion/enriched/markdown/renderer/ListRenderer.kt +43 -4
  78. package/android/src/main/java/com/swmansion/enriched/markdown/renderer/NodeRenderer.kt +9 -1
  79. package/android/src/main/java/com/swmansion/enriched/markdown/renderer/SoftBreakRenderer.kt +16 -0
  80. package/android/src/main/java/com/swmansion/enriched/markdown/renderer/SpanStyleCache.kt +35 -28
  81. package/android/src/main/java/com/swmansion/enriched/markdown/spans/BaseListSpan.kt +24 -0
  82. package/android/src/main/java/com/swmansion/enriched/markdown/spans/BlockquoteSpan.kt +174 -24
  83. package/android/src/main/java/com/swmansion/enriched/markdown/spans/CodeBackgroundSpan.kt +20 -82
  84. package/android/src/main/java/com/swmansion/enriched/markdown/spans/CodeBlockSpan.kt +13 -16
  85. package/android/src/main/java/com/swmansion/enriched/markdown/spans/CodeSpan.kt +1 -1
  86. package/android/src/main/java/com/swmansion/enriched/markdown/spans/EmphasisSpan.kt +1 -1
  87. package/android/src/main/java/com/swmansion/enriched/markdown/spans/ImageSpan.kt +182 -46
  88. package/android/src/main/java/com/swmansion/enriched/markdown/spans/InlineChipPainter.kt +140 -0
  89. package/android/src/main/java/com/swmansion/enriched/markdown/spans/LinkChipSpans.kt +177 -0
  90. package/android/src/main/java/com/swmansion/enriched/markdown/spans/LinkSpan.kt +1 -6
  91. package/android/src/main/java/com/swmansion/enriched/markdown/spans/ListItemSpacingSpan.kt +33 -0
  92. package/android/src/main/java/com/swmansion/enriched/markdown/spans/ListMarkerAnchorSpan.kt +38 -0
  93. package/android/src/main/java/com/swmansion/enriched/markdown/spans/OrderedListSpan.kt +2 -0
  94. package/android/src/main/java/com/swmansion/enriched/markdown/spans/StrongSpan.kt +1 -1
  95. package/android/src/main/java/com/swmansion/enriched/markdown/spans/TaskListSpan.kt +3 -2
  96. package/android/src/main/java/com/swmansion/enriched/markdown/spans/UnorderedListSpan.kt +3 -2
  97. package/android/src/main/java/com/swmansion/enriched/markdown/styles/BlockquoteStyle.kt +6 -0
  98. package/android/src/main/java/com/swmansion/enriched/markdown/styles/CodeBlockStyle.kt +26 -0
  99. package/android/src/main/java/com/swmansion/enriched/markdown/styles/ImageStyle.kt +7 -1
  100. package/android/src/main/java/com/swmansion/enriched/markdown/styles/InlineMathStyle.kt +16 -1
  101. package/android/src/main/java/com/swmansion/enriched/markdown/styles/LinkStyle.kt +36 -1
  102. package/android/src/main/java/com/swmansion/enriched/markdown/styles/LinkVariantEntry.kt +7 -3
  103. package/android/src/main/java/com/swmansion/enriched/markdown/styles/ListStyle.kt +4 -1
  104. package/android/src/main/java/com/swmansion/enriched/markdown/styles/MathStyle.kt +3 -0
  105. package/android/src/main/java/com/swmansion/enriched/markdown/styles/StyleConfig.kt +13 -4
  106. package/android/src/main/java/com/swmansion/enriched/markdown/styles/TableStyle.kt +6 -0
  107. package/android/src/main/java/com/swmansion/enriched/markdown/utils/common/CodeBlockHighlighter.kt +90 -0
  108. package/android/src/main/java/com/swmansion/enriched/markdown/utils/common/CodeBlockNode.kt +57 -0
  109. package/android/src/main/java/com/swmansion/enriched/markdown/utils/common/FeatureFlags.kt +1 -0
  110. package/android/src/main/java/com/swmansion/enriched/markdown/utils/common/MarkdownSegment.kt +9 -0
  111. package/android/src/main/java/com/swmansion/enriched/markdown/utils/common/MarkdownViewManagerUtils.kt +84 -7
  112. package/android/src/main/java/com/swmansion/enriched/markdown/utils/common/ReadableMapExtensions.kt +3 -0
  113. package/android/src/main/java/com/swmansion/enriched/markdown/utils/common/RenderedSegment.kt +10 -0
  114. package/android/src/main/java/com/swmansion/enriched/markdown/utils/common/SegmentSignature.kt +1 -0
  115. package/android/src/main/java/com/swmansion/enriched/markdown/utils/common/StreamingMarkdownFilter.kt +83 -5
  116. package/android/src/main/java/com/swmansion/enriched/markdown/utils/common/serialization/MarkdownASTSerializer.kt +4 -0
  117. package/android/src/main/java/com/swmansion/enriched/markdown/utils/input/MarkdownStyleParser.kt +74 -44
  118. package/android/src/main/java/com/swmansion/enriched/markdown/utils/input/PasteTextUtils.kt +52 -0
  119. package/android/src/main/java/com/swmansion/enriched/markdown/utils/text/ImageCache.kt +26 -3
  120. package/android/src/main/java/com/swmansion/enriched/markdown/utils/text/ImageDownloader.kt +22 -9
  121. package/android/src/main/java/com/swmansion/enriched/markdown/utils/text/LocalImageLoader.kt +161 -0
  122. package/android/src/main/java/com/swmansion/enriched/markdown/utils/text/conversion/HTMLGenerator.kt +2 -1
  123. package/android/src/main/java/com/swmansion/enriched/markdown/utils/text/conversion/MarkdownExtractor.kt +6 -0
  124. package/android/src/main/java/com/swmansion/enriched/markdown/utils/text/extensions/TextPaintExtensions.kt +23 -0
  125. package/android/src/main/java/com/swmansion/enriched/markdown/utils/text/interaction/CheckboxTouchHelper.kt +7 -0
  126. package/android/src/main/java/com/swmansion/enriched/markdown/utils/text/interaction/TaskListTapUtils.kt +41 -21
  127. package/android/src/main/java/com/swmansion/enriched/markdown/utils/text/span/BlockSpacing.kt +15 -8
  128. package/android/src/main/java/com/swmansion/enriched/markdown/utils/text/view/HeadlessActionMode.kt +88 -0
  129. package/android/src/main/java/com/swmansion/enriched/markdown/utils/text/view/LinkLayoutCollector.kt +100 -0
  130. package/android/src/main/java/com/swmansion/enriched/markdown/utils/text/view/LinkLongPressMovementMethod.kt +58 -27
  131. package/android/src/main/java/com/swmansion/enriched/markdown/utils/text/view/SelectionActionMode.kt +72 -16
  132. package/android/src/main/java/com/swmansion/enriched/markdown/utils/text/view/SelectionChangeReporter.kt +232 -0
  133. package/android/src/main/java/com/swmansion/enriched/markdown/views/BlockMenuOptions.kt +64 -0
  134. package/android/src/main/java/com/swmansion/enriched/markdown/views/CodeBlockContainerView.kt +414 -0
  135. package/android/src/main/java/com/swmansion/enriched/markdown/views/ContextMenuPopup.kt +9 -6
  136. package/android/src/main/java/com/swmansion/enriched/markdown/views/CopyGlyph.kt +101 -0
  137. package/android/src/main/java/com/swmansion/enriched/markdown/views/TableContainerView.kt +61 -11
  138. package/android/src/main/jni/CMakeLists.txt +53 -0
  139. package/android/src/main/jni/react/renderer/components/EnrichedMarkdownTextSpec/MarkdownContainerShadowNode.cpp +10 -0
  140. package/android/src/main/jni/react/renderer/components/EnrichedMarkdownTextSpec/MarkdownContainerShadowNode.h +11 -2
  141. package/android/src/main/jni/react/renderer/components/EnrichedMarkdownTextSpec/MarkdownTextShadowNode.cpp +10 -0
  142. package/android/src/main/jni/react/renderer/components/EnrichedMarkdownTextSpec/MarkdownTextShadowNode.h +12 -2
  143. package/android/src/main/jni/react/renderer/components/EnrichedMarkdownTextSpec/MarkdownTextState.cpp +9 -0
  144. package/android/src/main/jni/react/renderer/components/EnrichedMarkdownTextSpec/MarkdownTextState.h +24 -0
  145. package/android/src/main/jni/react/renderer/components/EnrichedMarkdownTextSpec/conversions.h +16 -0
  146. package/android/src/math/java/com/swmansion/enriched/markdown/input/math/MathChipControllerImpl.kt +21 -4
  147. package/android/src/math/java/com/swmansion/enriched/markdown/renderer/MathInlineRenderer.kt +8 -2
  148. package/android/src/math/java/com/swmansion/enriched/markdown/spans/MathChipSpan.kt +1 -1
  149. package/android/src/math/java/com/swmansion/enriched/markdown/spans/MathInlineSpan.kt +13 -6
  150. package/android/src/math/java/com/swmansion/enriched/markdown/spans/MathMeasureHelper.kt +2 -1
  151. package/android/src/math/java/com/swmansion/enriched/markdown/views/MathContainerView.kt +26 -8
  152. package/cpp/highlight/CodeBlockHighlighter.cpp +284 -0
  153. package/cpp/highlight/CodeBlockHighlighter.hpp +66 -0
  154. package/cpp/highlight/CodeBlockLanguages.cpp +138 -0
  155. package/cpp/highlight/CodeBlockLanguages.hpp +25 -0
  156. package/cpp/highlight/HighlightGrammars.hpp +28 -0
  157. package/cpp/highlight/code_highlight_podspec.rb +211 -0
  158. package/cpp/highlight/gen-registry.mjs +155 -0
  159. package/cpp/highlight/grammar-versions.json +159 -0
  160. package/cpp/highlight/vendor/generated/generated_queries.h +1665 -0
  161. package/cpp/highlight/vendor/generated/generated_registry.cpp +59 -0
  162. package/cpp/parser/MD4CParser.cpp +173 -61
  163. package/cpp/parser/MD4CParser.hpp +1 -0
  164. package/cpp/parser/MarkdownASTNode.hpp +2 -1
  165. package/cpp/wasm/ASTSerializer.cpp +2 -0
  166. package/cpp/wasm/build.sh +1 -0
  167. package/cpp/wasm/md4c_wasm.cpp +3 -1
  168. package/docs/ACCESSIBILITY.md +14 -2
  169. package/docs/API_REFERENCE.md +405 -12
  170. package/docs/BREAKING_CHANGES.md +129 -0
  171. package/docs/CODE_HIGHLIGHT.md +133 -0
  172. package/docs/COPY_OPTIONS.md +61 -3
  173. package/docs/ELEMENTS_STRUCTURE.md +52 -4
  174. package/docs/IMAGE_CACHING.md +30 -0
  175. package/docs/INPUT.md +110 -11
  176. package/docs/LATEX_MATH.md +87 -45
  177. package/docs/MACOS.md +1 -1
  178. package/docs/MARKDOWN_STREAMING.md +27 -1
  179. package/docs/MENTIONS.md +8 -1
  180. package/docs/NATIVE_ASSETS.md +127 -0
  181. package/docs/RTL.md +1 -1
  182. package/docs/STYLES.md +73 -6
  183. package/docs/TESTING.md +112 -0
  184. package/docs/TEXT.md +18 -6
  185. package/docs/WEB.md +4 -1
  186. package/ios/EnrichedMarkdown.h +7 -0
  187. package/ios/EnrichedMarkdown.mm +583 -76
  188. package/ios/EnrichedMarkdownText.h +7 -0
  189. package/ios/EnrichedMarkdownText.mm +299 -73
  190. package/ios/attachments/ENRMImageAttachment.h +9 -0
  191. package/ios/attachments/ENRMImageAttachment.m +143 -40
  192. package/ios/attachments/ENRMMathInlineAttachment+macOS.m +2 -1
  193. package/ios/attachments/ENRMMathInlineAttachment.h +5 -0
  194. package/ios/attachments/ENRMMathInlineAttachment.m +50 -82
  195. package/ios/attachments/ENRMMathInlineAttachmentShared.h +2 -0
  196. package/ios/generated/ReactCodegen/EnrichedMarkdownTextSpec/EventEmitters.cpp +223 -0
  197. package/ios/generated/ReactCodegen/EnrichedMarkdownTextSpec/EventEmitters.h +183 -0
  198. package/ios/generated/ReactCodegen/EnrichedMarkdownTextSpec/Props.cpp +65 -0
  199. package/ios/generated/ReactCodegen/EnrichedMarkdownTextSpec/Props.h +1086 -61
  200. package/ios/generated/ReactCodegen/EnrichedMarkdownTextSpec/RCTComponentViewHelpers.h +181 -2
  201. package/ios/input/ENRMAutoLinkDetector.h +2 -1
  202. package/ios/input/ENRMAutoLinkDetector.mm +79 -41
  203. package/ios/input/ENRMBlockEditCoordinator.h +71 -0
  204. package/ios/input/ENRMBlockEditCoordinator.mm +195 -0
  205. package/ios/input/ENRMBlockRange.h +28 -0
  206. package/ios/input/ENRMBlockRange.mm +30 -0
  207. package/ios/input/ENRMBlockStore.h +56 -0
  208. package/ios/input/ENRMBlockStore.mm +275 -0
  209. package/ios/input/ENRMClipboardCoordinator.h +45 -0
  210. package/ios/input/ENRMClipboardCoordinator.mm +120 -0
  211. package/ios/input/ENRMDetectorPipeline.h +2 -1
  212. package/ios/input/ENRMEditPipeline.h +76 -0
  213. package/ios/input/ENRMEditPipeline.mm +228 -0
  214. package/ios/input/ENRMEditSession.h +36 -0
  215. package/ios/input/ENRMEditSession.mm +63 -0
  216. package/ios/input/ENRMFormattingStore.h +17 -0
  217. package/ios/input/ENRMFormattingStore.mm +95 -105
  218. package/ios/input/ENRMInputBlockType.h +91 -0
  219. package/ios/input/ENRMInputBlockType.mm +5 -0
  220. package/ios/input/ENRMInputDecorationDrawer.h +18 -0
  221. package/ios/input/ENRMInputEventEmitter.h +56 -0
  222. package/ios/input/ENRMInputEventEmitter.mm +308 -0
  223. package/ios/input/ENRMInputFormatter.h +29 -69
  224. package/ios/input/ENRMInputFormatter.mm +216 -124
  225. package/ios/input/ENRMInputFormatterStyle.h +99 -0
  226. package/ios/input/ENRMInputFormatterStyle.mm +188 -0
  227. package/ios/input/ENRMInputLayoutManager.h +9 -0
  228. package/ios/input/ENRMInputLayoutManager.mm +30 -0
  229. package/ios/input/ENRMInputListMarkerDrawer.h +32 -0
  230. package/ios/input/ENRMInputListMarkerDrawer.mm +426 -0
  231. package/ios/input/ENRMInputParser.h +5 -6
  232. package/ios/input/ENRMInputParser.mm +461 -178
  233. package/ios/input/ENRMInputRemend.mm +2 -2
  234. package/ios/input/ENRMInputStyleStateBuilder.h +40 -0
  235. package/ios/input/ENRMInputStyleStateBuilder.mm +60 -0
  236. package/ios/input/ENRMInputTextView.mm +103 -8
  237. package/ios/input/ENRMInputTypingAttributesController.h +42 -0
  238. package/ios/input/ENRMInputTypingAttributesController.mm +203 -0
  239. package/ios/input/ENRMLinkCoordinator.h +41 -0
  240. package/ios/input/ENRMLinkCoordinator.mm +89 -0
  241. package/ios/input/ENRMMarkdownSerializer.h +29 -5
  242. package/ios/input/ENRMMarkdownSerializer.mm +170 -48
  243. package/ios/input/ENRMMathAtom.h +26 -0
  244. package/ios/input/ENRMMathAtom.mm +12 -0
  245. package/ios/input/ENRMMentionCoordinator.h +45 -0
  246. package/ios/input/ENRMMentionCoordinator.mm +167 -0
  247. package/ios/input/ENRMRangeEditAdjustment.h +38 -0
  248. package/ios/input/ENRMRangeEditAdjustment.mm +91 -0
  249. package/ios/input/ENRMRangeStoreUtils.h +39 -0
  250. package/ios/input/EnrichedMarkdownTextInput+ContextMenu.mm +6 -6
  251. package/ios/input/EnrichedMarkdownTextInput+Internal.h +11 -3
  252. package/ios/input/EnrichedMarkdownTextInput.h +7 -1
  253. package/ios/input/EnrichedMarkdownTextInput.mm +1089 -1023
  254. package/ios/input/InputStylePropsUtils.h +109 -68
  255. package/ios/input/internals/EnrichedMarkdownTextInputShadowNode.mm +2 -1
  256. package/ios/input/styles/ENRMBlockHandler.h +46 -0
  257. package/ios/input/styles/ENRMHeadingBlockHandler.h +15 -0
  258. package/ios/input/styles/ENRMHeadingBlockHandler.mm +38 -0
  259. package/ios/input/styles/ENRMOrderedListBlockHandler.h +14 -0
  260. package/ios/input/styles/ENRMOrderedListBlockHandler.mm +48 -0
  261. package/ios/input/styles/ENRMUnorderedListBlockHandler.h +15 -0
  262. package/ios/input/styles/ENRMUnorderedListBlockHandler.mm +51 -0
  263. package/ios/internals/ENRMViewFreeMeasurement.h +331 -0
  264. package/ios/internals/EnrichedMarkdownShadowNode.h +1 -3
  265. package/ios/internals/EnrichedMarkdownShadowNode.mm +16 -20
  266. package/ios/internals/EnrichedMarkdownTextShadowNode.h +1 -3
  267. package/ios/internals/EnrichedMarkdownTextShadowNode.mm +15 -20
  268. package/ios/internals/MeasurementCache.h +41 -9
  269. package/ios/internals/ShadowMeasurementUtils.h +63 -58
  270. package/ios/math/ENRMMathChipController.h +74 -0
  271. package/ios/math/ENRMMathChipController.mm +476 -0
  272. package/ios/math/ENRMRaTeXBridge.swift +27 -6
  273. package/ios/parser/ENRMMarkdownParser.h +1 -8
  274. package/ios/parser/ENRMMarkdownParser.mm +2 -11
  275. package/ios/parser/MarkdownASTNode.h +2 -1
  276. package/ios/parser/MarkdownParserBridge.mm +4 -0
  277. package/ios/renderer/AttributedRenderer.m +20 -2
  278. package/ios/renderer/BaseRenderer.h +17 -2
  279. package/ios/renderer/BaseRenderer.m +30 -0
  280. package/ios/renderer/BlockquoteRenderer.h +1 -1
  281. package/ios/renderer/BlockquoteRenderer.m +144 -35
  282. package/ios/renderer/CodeBlockRenderer.h +1 -1
  283. package/ios/renderer/CodeBlockRenderer.m +27 -23
  284. package/ios/renderer/CodeRenderer.h +1 -1
  285. package/ios/renderer/CodeRenderer.m +3 -1
  286. package/ios/renderer/ENRMImageRenderer.h +1 -1
  287. package/ios/renderer/ENRMImageRenderer.m +5 -1
  288. package/ios/renderer/ENRMMathInlineRenderer.h +1 -1
  289. package/ios/renderer/ENRMMathInlineRenderer.m +6 -1
  290. package/ios/renderer/ENRMSpoilerRenderer.h +1 -1
  291. package/ios/renderer/ENRMSpoilerRenderer.m +3 -1
  292. package/ios/renderer/EmphasisRenderer.h +1 -1
  293. package/ios/renderer/EmphasisRenderer.m +3 -1
  294. package/ios/renderer/HeadingRenderer.h +1 -1
  295. package/ios/renderer/HeadingRenderer.m +13 -6
  296. package/ios/renderer/HighlightRenderer.h +1 -1
  297. package/ios/renderer/HighlightRenderer.m +3 -1
  298. package/ios/renderer/LinkRenderer.h +1 -1
  299. package/ios/renderer/LinkRenderer.m +50 -16
  300. package/ios/renderer/ListItemRenderer.h +13 -1
  301. package/ios/renderer/ListItemRenderer.m +102 -44
  302. package/ios/renderer/ListRenderer.h +2 -2
  303. package/ios/renderer/ListRenderer.m +63 -25
  304. package/ios/renderer/ParagraphRenderer.h +1 -1
  305. package/ios/renderer/ParagraphRenderer.m +16 -8
  306. package/ios/renderer/RenderContext.h +10 -0
  307. package/ios/renderer/RenderContext.m +44 -0
  308. package/ios/renderer/RendererFactory.m +14 -0
  309. package/ios/renderer/StrikethroughRenderer.h +1 -1
  310. package/ios/renderer/StrikethroughRenderer.m +3 -1
  311. package/ios/renderer/StrongRenderer.h +1 -1
  312. package/ios/renderer/StrongRenderer.m +3 -1
  313. package/ios/renderer/SubscriptRenderer.h +1 -1
  314. package/ios/renderer/SubscriptRenderer.m +3 -1
  315. package/ios/renderer/SuperscriptRenderer.h +1 -1
  316. package/ios/renderer/SuperscriptRenderer.m +3 -1
  317. package/ios/renderer/TextRenderer.h +2 -2
  318. package/ios/renderer/TextRenderer.m +3 -1
  319. package/ios/renderer/ThematicBreakRenderer.h +1 -1
  320. package/ios/renderer/ThematicBreakRenderer.m +3 -1
  321. package/ios/renderer/UnderlineRenderer.h +1 -1
  322. package/ios/renderer/UnderlineRenderer.m +3 -1
  323. package/ios/styles/StyleConfig.h +42 -0
  324. package/ios/styles/StyleConfig.mm +216 -0
  325. package/ios/utils/BlockquoteBorder.h +6 -0
  326. package/ios/utils/BlockquoteBorder.m +249 -52
  327. package/ios/utils/CodeBackground.m +3 -65
  328. package/ios/utils/CodeBlockBackground.m +16 -2
  329. package/ios/utils/ENRMAtomicSize.h +65 -0
  330. package/ios/utils/ENRMBlockMenu.h +66 -0
  331. package/ios/utils/ENRMChipDrawing.h +24 -0
  332. package/ios/utils/ENRMChipDrawing.m +83 -0
  333. package/ios/utils/ENRMCodeBlockContent.h +37 -0
  334. package/ios/utils/ENRMCodeBlockContent.mm +79 -0
  335. package/ios/utils/ENRMCodeBlockHighlighter.h +37 -0
  336. package/ios/utils/ENRMCodeBlockHighlighter.mm +51 -0
  337. package/ios/utils/ENRMFeatureFlags.h +7 -0
  338. package/ios/utils/ENRMImageDownloader.h +11 -1
  339. package/ios/utils/ENRMImageDownloader.m +60 -16
  340. package/ios/utils/ENRMLinkChip.h +70 -0
  341. package/ios/utils/ENRMLinkChip.m +213 -0
  342. package/ios/utils/ENRMLinkLayout.h +50 -0
  343. package/ios/utils/ENRMLinkLayout.m +45 -0
  344. package/ios/utils/ENRMLocalImageLoader.h +31 -0
  345. package/ios/utils/ENRMLocalImageLoader.m +68 -0
  346. package/ios/utils/ENRMMathFallback.h +26 -0
  347. package/ios/utils/ENRMMathFallback.m +18 -0
  348. package/ios/utils/ENRMSelectionChange.h +120 -0
  349. package/ios/utils/ENRMSelectionChange.m +282 -0
  350. package/ios/utils/ENRMTextViewSetup.h +35 -17
  351. package/ios/utils/EditMenuUtils+macOS.m +4 -1
  352. package/ios/utils/EditMenuUtils.h +35 -6
  353. package/ios/utils/EditMenuUtils.m +188 -11
  354. package/ios/utils/HTMLGenerator.m +2 -1
  355. package/ios/utils/ImageRequestHeaderUtils.h +35 -0
  356. package/ios/utils/LastElementUtils.h +1 -0
  357. package/ios/utils/ListMarkerDrawer.m +29 -42
  358. package/ios/utils/MarkdownASTSerializer.m +4 -0
  359. package/ios/utils/MarkdownAccessibilityElementBuilder.m +3 -1
  360. package/ios/utils/MarkdownExtractor.m +2 -1
  361. package/ios/utils/ParagraphStyleUtils.h +5 -0
  362. package/ios/utils/ParagraphStyleUtils.m +77 -17
  363. package/ios/utils/RTFExportUtils.m +2 -0
  364. package/ios/utils/RenderedMarkdownSegment.h +13 -1
  365. package/ios/utils/RenderedMarkdownSegment.m +20 -0
  366. package/ios/utils/SegmentRenderer.m +17 -4
  367. package/ios/utils/StreamingMarkdownFilter.h +11 -1
  368. package/ios/utils/StreamingMarkdownFilter.m +98 -2
  369. package/ios/utils/StylePropsUtils.h +110 -1
  370. package/ios/utils/TaskListTapUtils.m +24 -0
  371. package/ios/utils/TextViewLayoutManager.mm +3 -0
  372. package/ios/views/ENRMCodeBlockContainerView.h +60 -0
  373. package/ios/views/ENRMCodeBlockContainerView.m +569 -0
  374. package/ios/views/ENRMMathContainerView.h +23 -0
  375. package/ios/views/ENRMMathContainerView.m +87 -20
  376. package/ios/views/TableContainerView.h +32 -0
  377. package/ios/views/TableContainerView.m +291 -175
  378. package/jest.d.ts +1 -0
  379. package/jest.js +5 -0
  380. package/lib/module/EnrichedMarkdownNativeComponent.ts +203 -1
  381. package/lib/module/EnrichedMarkdownTextInput.js +84 -5
  382. package/lib/module/EnrichedMarkdownTextInput.js.map +1 -1
  383. package/lib/module/EnrichedMarkdownTextInputNativeComponent.ts +78 -5
  384. package/lib/module/EnrichedMarkdownTextNativeComponent.ts +204 -1
  385. package/lib/module/headingDefaults.js +34 -0
  386. package/lib/module/headingDefaults.js.map +1 -0
  387. package/lib/module/index.js.map +1 -1
  388. package/lib/module/jest/index.js +205 -0
  389. package/lib/module/jest/index.js.map +1 -0
  390. package/lib/module/native/EnrichedMarkdownText.js +199 -15
  391. package/lib/module/native/EnrichedMarkdownText.js.map +1 -1
  392. package/lib/module/normalizeMarkdownStyle.js +98 -23
  393. package/lib/module/normalizeMarkdownStyle.js.map +1 -1
  394. package/lib/module/normalizeMarkdownStyle.web.js +73 -22
  395. package/lib/module/normalizeMarkdownStyle.web.js.map +1 -1
  396. package/lib/module/normalizeMarkdownTextInputStyle.js +62 -15
  397. package/lib/module/normalizeMarkdownTextInputStyle.js.map +1 -1
  398. package/lib/module/normalizeMenuItem.js +1 -1
  399. package/lib/module/utils/textInputState.js +26 -0
  400. package/lib/module/utils/textInputState.js.map +1 -0
  401. package/lib/module/web/EnrichedMarkdownText.js +15 -8
  402. package/lib/module/web/EnrichedMarkdownText.js.map +1 -1
  403. package/lib/module/web/parseMarkdown.js +4 -3
  404. package/lib/module/web/parseMarkdown.js.map +1 -1
  405. package/lib/module/web/renderers/InlineRenderers.js +102 -3
  406. package/lib/module/web/renderers/InlineRenderers.js.map +1 -1
  407. package/lib/module/web/renderers/ListRenderers.js +7 -2
  408. package/lib/module/web/renderers/ListRenderers.js.map +1 -1
  409. package/lib/module/web/renderers/index.js +7 -4
  410. package/lib/module/web/renderers/index.js.map +1 -1
  411. package/lib/module/web/styles.js +101 -6
  412. package/lib/module/web/styles.js.map +1 -1
  413. package/lib/module/web/utils.js +14 -0
  414. package/lib/module/web/utils.js.map +1 -1
  415. package/lib/module/web/wasm/md4c.js +0 -0
  416. package/lib/module/web/wasm/md4c.js.map +1 -1
  417. package/lib/typescript/src/EnrichedMarkdownNativeComponent.d.ts +185 -2
  418. package/lib/typescript/src/EnrichedMarkdownNativeComponent.d.ts.map +1 -1
  419. package/lib/typescript/src/EnrichedMarkdownTextInput.d.ts +94 -9
  420. package/lib/typescript/src/EnrichedMarkdownTextInput.d.ts.map +1 -1
  421. package/lib/typescript/src/EnrichedMarkdownTextInputNativeComponent.d.ts +69 -5
  422. package/lib/typescript/src/EnrichedMarkdownTextInputNativeComponent.d.ts.map +1 -1
  423. package/lib/typescript/src/EnrichedMarkdownTextNativeComponent.d.ts +185 -2
  424. package/lib/typescript/src/EnrichedMarkdownTextNativeComponent.d.ts.map +1 -1
  425. package/lib/typescript/src/headingDefaults.d.ts +9 -0
  426. package/lib/typescript/src/headingDefaults.d.ts.map +1 -0
  427. package/lib/typescript/src/index.d.ts +3 -3
  428. package/lib/typescript/src/index.d.ts.map +1 -1
  429. package/lib/typescript/src/index.web.d.ts +2 -2
  430. package/lib/typescript/src/index.web.d.ts.map +1 -1
  431. package/lib/typescript/src/jest/index.d.ts +6 -0
  432. package/lib/typescript/src/jest/index.d.ts.map +1 -0
  433. package/lib/typescript/src/native/EnrichedMarkdownText.d.ts +5 -5
  434. package/lib/typescript/src/native/EnrichedMarkdownText.d.ts.map +1 -1
  435. package/lib/typescript/src/normalizeMarkdownStyle.d.ts.map +1 -1
  436. package/lib/typescript/src/normalizeMarkdownStyle.web.d.ts.map +1 -1
  437. package/lib/typescript/src/normalizeMarkdownTextInputStyle.d.ts +19 -5
  438. package/lib/typescript/src/normalizeMarkdownTextInputStyle.d.ts.map +1 -1
  439. package/lib/typescript/src/types/MarkdownStyle.d.ts +122 -5
  440. package/lib/typescript/src/types/MarkdownStyle.d.ts.map +1 -1
  441. package/lib/typescript/src/types/MarkdownStyleInternal.d.ts +39 -0
  442. package/lib/typescript/src/types/MarkdownStyleInternal.d.ts.map +1 -1
  443. package/lib/typescript/src/types/MarkdownTextProps.d.ts +207 -10
  444. package/lib/typescript/src/types/MarkdownTextProps.d.ts.map +1 -1
  445. package/lib/typescript/src/types/MarkdownTextProps.web.d.ts +60 -1
  446. package/lib/typescript/src/types/MarkdownTextProps.web.d.ts.map +1 -1
  447. package/lib/typescript/src/types/events.d.ts +85 -0
  448. package/lib/typescript/src/types/events.d.ts.map +1 -1
  449. package/lib/typescript/src/utils/textInputState.d.ts +24 -0
  450. package/lib/typescript/src/utils/textInputState.d.ts.map +1 -0
  451. package/lib/typescript/src/web/EnrichedMarkdownText.d.ts +1 -1
  452. package/lib/typescript/src/web/EnrichedMarkdownText.d.ts.map +1 -1
  453. package/lib/typescript/src/web/parseMarkdown.d.ts +1 -1
  454. package/lib/typescript/src/web/parseMarkdown.d.ts.map +1 -1
  455. package/lib/typescript/src/web/renderers/InlineRenderers.d.ts.map +1 -1
  456. package/lib/typescript/src/web/renderers/ListRenderers.d.ts.map +1 -1
  457. package/lib/typescript/src/web/renderers/index.d.ts +2 -1
  458. package/lib/typescript/src/web/renderers/index.d.ts.map +1 -1
  459. package/lib/typescript/src/web/styles.d.ts +2 -1
  460. package/lib/typescript/src/web/styles.d.ts.map +1 -1
  461. package/lib/typescript/src/web/types.d.ts +10 -2
  462. package/lib/typescript/src/web/types.d.ts.map +1 -1
  463. package/lib/typescript/src/web/utils.d.ts +4 -0
  464. package/lib/typescript/src/web/utils.d.ts.map +1 -1
  465. package/package.json +36 -9
  466. package/postinstall.mjs +131 -0
  467. package/ratex-version.json +21 -0
  468. package/src/EnrichedMarkdownNativeComponent.ts +203 -1
  469. package/src/EnrichedMarkdownTextInput.tsx +159 -8
  470. package/src/EnrichedMarkdownTextInputNativeComponent.ts +78 -5
  471. package/src/EnrichedMarkdownTextNativeComponent.ts +204 -1
  472. package/src/headingDefaults.ts +21 -0
  473. package/src/index.tsx +15 -0
  474. package/src/index.web.tsx +6 -1
  475. package/src/jest/index.tsx +236 -0
  476. package/src/native/EnrichedMarkdownText.tsx +260 -11
  477. package/src/normalizeMarkdownStyle.ts +117 -16
  478. package/src/normalizeMarkdownStyle.web.ts +76 -15
  479. package/src/normalizeMarkdownTextInputStyle.ts +110 -35
  480. package/src/normalizeMenuItem.ts +1 -1
  481. package/src/types/MarkdownStyle.ts +125 -5
  482. package/src/types/MarkdownStyleInternal.ts +51 -0
  483. package/src/types/MarkdownTextProps.ts +215 -10
  484. package/src/types/MarkdownTextProps.web.ts +62 -1
  485. package/src/types/events.ts +90 -0
  486. package/src/utils/textInputState.ts +35 -0
  487. package/src/web/EnrichedMarkdownText.tsx +26 -5
  488. package/src/web/parseMarkdown.ts +6 -2
  489. package/src/web/renderers/InlineRenderers.tsx +116 -3
  490. package/src/web/renderers/ListRenderers.tsx +14 -2
  491. package/src/web/renderers/index.tsx +6 -2
  492. package/src/web/styles.ts +114 -5
  493. package/src/web/types.ts +10 -1
  494. package/src/web/utils.ts +9 -0
  495. package/src/web/wasm/md4c.js +0 -0
  496. package/vendor-grammars.mjs +511 -0
  497. package/vendor-ratex.mjs +173 -0
  498. package/app.plugin.js +0 -2
  499. package/plugin/build/withAndroidMath.js +0 -19
  500. package/plugin/build/withIosMath.js +0 -28
  501. package/plugin/build/withReactNativeEnrichedMarkdown.js +0 -11
  502. package/plugin/src/withAndroidMath.ts +0 -24
  503. package/plugin/src/withIosMath.ts +0 -35
  504. package/plugin/src/withReactNativeEnrichedMarkdown.ts +0 -17
  505. package/plugin/tsconfig.build.json +0 -16
@@ -1,4 +1,5 @@
1
1
  #import "EditMenuUtils.h"
2
+ #import "ENRMLinkChip.h"
2
3
  #import "PasteboardUtils.h"
3
4
  #import "StyleConfig.h"
4
5
  #include <TargetConditionals.h>
@@ -10,14 +11,34 @@ static NSString *const kActionIdentifierCopy = @"com.swmansion.enriched.markdown
10
11
  static NSString *const kActionIdentifierCopyMarkdown = @"com.swmansion.enriched.markdown.copyMarkdown";
11
12
  static NSString *const kActionIdentifierCopyImageURL = @"com.swmansion.enriched.markdown.copyImageURL";
12
13
 
13
- static UIAction *createCopyAction(NSAttributedString *selectedText, NSString *markdown, StyleConfig *styleConfig,
14
- NSString *copyLabel)
14
+ static UIAction *_Nullable createCopyAction(NSAttributedString *selectedText, NSString *markdown, BOOL fullSelection,
15
+ StyleConfig *styleConfig, ENRMSelectionMenuConfig selectionMenuConfig,
16
+ ENRMCopyRequestHandler _Nullable onCopyRequest)
15
17
  {
16
- return [UIAction actionWithTitle:copyLabel
18
+ if (!selectionMenuConfig.copyEnabled)
19
+ return nil;
20
+
21
+ if (selectionMenuConfig.interceptCopy && onCopyRequest) {
22
+ NSString *text = selectedText.string;
23
+ NSString *copied = markdown.length > 0 ? markdown : text;
24
+ return [UIAction actionWithTitle:selectionMenuConfig.copyLabel
25
+ image:[RCTUIImage systemImageNamed:@"doc.on.doc"]
26
+ identifier:kActionIdentifierCopy
27
+ handler:^(__kindof UIAction *action) { onCopyRequest(copied, text, fullSelection); }];
28
+ }
29
+
30
+ BOOL writesMarkdown = selectionMenuConfig.copyFormatMarkdown;
31
+ return [UIAction actionWithTitle:selectionMenuConfig.copyLabel
17
32
  image:[RCTUIImage systemImageNamed:@"doc.on.doc"]
18
33
  identifier:kActionIdentifierCopy
19
34
  handler:^(__kindof UIAction *action) {
20
- copyAttributedStringToPasteboard(selectedText, markdown, styleConfig);
35
+ if (!writesMarkdown) {
36
+ copyAttributedStringToPasteboard(selectedText, markdown, styleConfig);
37
+ } else {
38
+ // Plain text only: with HTML/RTF alongside, rich-paste targets
39
+ // would take those and drop the Markdown.
40
+ copyStringToPasteboard(markdown.length > 0 ? markdown : selectedText.string);
41
+ }
21
42
  }];
22
43
  }
23
44
 
@@ -47,13 +68,37 @@ static UIAction *_Nullable createCopyImageURLAction(NSArray<NSString *> *imageUR
47
68
  handler:^(__kindof UIAction *action) { copyStringToPasteboard(urlsToCopy); }];
48
69
  }
49
70
 
50
- static UIMenu *createEnhancedStandardEditMenu(UIMenu *originalMenu, UIAction *copyAction)
71
+ /// Rebuilds the standard-edit menu with the system Copy swapped for the enhanced
72
+ /// copy action, or dropped when `copyAction` is nil (Copy disabled). All other
73
+ /// system items are kept — dropping them would remove Select All, which on
74
+ /// iOS 16+ is the only way to start a selection from the long-press menu of a
75
+ /// non-editable text view.
76
+ static UIMenu *createEnhancedStandardEditMenu(UIMenu *originalMenu, UIAction *_Nullable copyAction)
51
77
  {
78
+ NSMutableArray<UIMenuElement *> *children = [NSMutableArray arrayWithCapacity:originalMenu.children.count];
79
+ BOOL replacedCopy = NO;
80
+
81
+ for (UIMenuElement *element in originalMenu.children) {
82
+ if (!replacedCopy && [element isKindOfClass:[UICommand class]] &&
83
+ ((UICommand *)element).action == @selector(copy:)) {
84
+ if (copyAction) {
85
+ [children addObject:copyAction];
86
+ }
87
+ replacedCopy = YES;
88
+ continue;
89
+ }
90
+ [children addObject:element];
91
+ }
92
+
93
+ if (!replacedCopy && copyAction) {
94
+ [children insertObject:copyAction atIndex:0];
95
+ }
96
+
52
97
  return [UIMenu menuWithTitle:originalMenu.title
53
98
  image:originalMenu.image
54
99
  identifier:originalMenu.identifier
55
100
  options:originalMenu.options
56
- children:@[ copyAction ]];
101
+ children:children];
57
102
  }
58
103
 
59
104
  static void addOptionalAction(NSMutableArray<UIMenuElement *> *array, UIAction *_Nullable action)
@@ -74,13 +119,19 @@ static void insertOptionalAction(NSMutableArray<UIMenuElement *> *array, UIActio
74
119
  UIMenu *buildEditMenuForSelection(NSAttributedString *attributedText, NSRange range, NSString *_Nullable cachedMarkdown,
75
120
  StyleConfig *styleConfig, NSArray<UIMenuElement *> *suggestedActions,
76
121
  NSArray<UIAction *> *_Nullable customActions,
77
- ENRMSelectionMenuConfig selectionMenuConfig) API_AVAILABLE(ios(16.0))
122
+ ENRMSelectionMenuConfig selectionMenuConfig,
123
+ ENRMCopyRequestHandler _Nullable onCopyRequest) API_AVAILABLE(ios(16.0))
78
124
  {
79
- NSAttributedString *selectedText = [attributedText attributedSubstringFromRange:range];
125
+ // Link spacers only reserve layout space; keep them out of every copied flavor.
126
+ NSAttributedString *selectedText =
127
+ ENRMAttributedStringByRemovingLinkSpacers([attributedText attributedSubstringFromRange:range]);
80
128
  NSString *markdown = markdownForRange(attributedText, range, cachedMarkdown);
81
129
  NSArray<NSString *> *imageURLs = imageURLsInRange(attributedText, range);
130
+ // Same threshold markdownForRange uses to return the cached markdown.
131
+ BOOL fullSelection = range.location == 0 && range.length >= attributedText.length - 1;
82
132
 
83
- UIAction *copyAction = createCopyAction(selectedText, markdown, styleConfig, selectionMenuConfig.copyLabel);
133
+ UIAction *copyAction =
134
+ createCopyAction(selectedText, markdown, fullSelection, styleConfig, selectionMenuConfig, onCopyRequest);
84
135
  UIAction *copyMarkdownAction = selectionMenuConfig.copyAsMarkdown
85
136
  ? createCopyMarkdownAction(markdown, selectionMenuConfig.copyAsMarkdownLabel)
86
137
  : nil;
@@ -88,6 +139,16 @@ UIMenu *buildEditMenuForSelection(NSAttributedString *attributedText, NSRange ra
88
139
  selectionMenuConfig.copyImageURL ? createCopyImageURLAction(imageURLs, selectionMenuConfig) : nil;
89
140
 
90
141
  NSMutableArray<UIMenuElement *> *result = [NSMutableArray array];
142
+
143
+ if (selectionMenuConfig.systemItemsNone) {
144
+ // Skip suggestedActions entirely. An empty result still yields an (empty)
145
+ // menu: returning nil would make UIKit present its default menu.
146
+ addOptionalAction(result, copyAction);
147
+ addOptionalAction(result, copyMarkdownAction);
148
+ addOptionalAction(result, copyImageURLAction);
149
+ return [UIMenu menuWithChildren:[(customActions ?: @[]) arrayByAddingObjectsFromArray:result]];
150
+ }
151
+
91
152
  BOOL foundStandardEditMenu = NO;
92
153
 
93
154
  for (UIMenuElement *element in suggestedActions) {
@@ -107,8 +168,8 @@ UIMenu *buildEditMenuForSelection(NSAttributedString *attributedText, NSRange ra
107
168
  }
108
169
 
109
170
  if (!foundStandardEditMenu) {
110
- [result insertObject:copyAction atIndex:0];
111
- insertOptionalAction(result, copyMarkdownAction, 1);
171
+ insertOptionalAction(result, copyMarkdownAction, 0);
172
+ insertOptionalAction(result, copyAction, 0);
112
173
  addOptionalAction(result, copyImageURLAction);
113
174
  }
114
175
 
@@ -119,4 +180,120 @@ UIMenu *buildEditMenuForSelection(NSAttributedString *attributedText, NSRange ra
119
180
  return [UIMenu menuWithChildren:result];
120
181
  }
121
182
 
183
+ #import <objc/runtime.h>
184
+
185
+ static const void *kSelectionEditMenuPresenterKey = &kSelectionEditMenuPresenterKey;
186
+
187
+ API_AVAILABLE(ios(16.0))
188
+ @interface ENRMSelectionEditMenuPresenter : NSObject <UIEditMenuInteractionDelegate>
189
+ @property (nonatomic, weak) UITextView *textView;
190
+ @property (nonatomic, strong) UIEditMenuInteraction *interaction;
191
+ @property (nonatomic, assign) NSRange range;
192
+ @end
193
+
194
+ @implementation ENRMSelectionEditMenuPresenter
195
+
196
+ - (UIMenu *)editMenuInteraction:(UIEditMenuInteraction *)interaction
197
+ menuForConfiguration:(UIEditMenuConfiguration *)configuration
198
+ suggestedActions:(NSArray<UIMenuElement *> *)suggestedActions
199
+ {
200
+ UITextView *textView = self.textView;
201
+ id<UITextViewDelegate> delegate = textView.delegate;
202
+ if (!textView || ![delegate respondsToSelector:@selector(textView:editMenuForTextInRange:suggestedActions:)]) {
203
+ return nil;
204
+ }
205
+ return [delegate textView:textView editMenuForTextInRange:textView.selectedRange suggestedActions:suggestedActions];
206
+ }
207
+
208
+ - (CGRect)editMenuInteraction:(UIEditMenuInteraction *)interaction
209
+ targetRectForConfiguration:(UIEditMenuConfiguration *)configuration
210
+ {
211
+ UITextView *textView = self.textView;
212
+ UITextRange *textRange = textView.selectedTextRange;
213
+ if (!textView || !textRange) {
214
+ return CGRectNull;
215
+ }
216
+ return [textView firstRectForRange:textRange];
217
+ }
218
+
219
+ @end
220
+
221
+ static BOOL selectionEditMenuTextViewHasActiveGesture(UITextView *textView)
222
+ {
223
+ for (UIGestureRecognizer *recognizer in textView.gestureRecognizers) {
224
+ if (recognizer.state == UIGestureRecognizerStateBegan || recognizer.state == UIGestureRecognizerStateChanged) {
225
+ return YES;
226
+ }
227
+ }
228
+ return NO;
229
+ }
230
+
231
+ static void presentSelectionEditMenu(UITextView *textView)
232
+ {
233
+ UITextRange *textRange = textView.selectedTextRange;
234
+ if (!textRange || textRange.isEmpty) {
235
+ return;
236
+ }
237
+ CGRect rect = [textView firstRectForRange:textRange];
238
+ if (CGRectIsNull(rect) || CGRectIsEmpty(rect)) {
239
+ return;
240
+ }
241
+ if (@available(iOS 16.0, *)) {
242
+ ENRMSelectionEditMenuPresenter *presenter = objc_getAssociatedObject(textView, kSelectionEditMenuPresenterKey);
243
+ if (!presenter) {
244
+ presenter = [[ENRMSelectionEditMenuPresenter alloc] init];
245
+ presenter.textView = textView;
246
+ presenter.interaction = [[UIEditMenuInteraction alloc] initWithDelegate:presenter];
247
+ [textView addInteraction:presenter.interaction];
248
+ objc_setAssociatedObject(textView, kSelectionEditMenuPresenterKey, presenter, OBJC_ASSOCIATION_RETAIN_NONATOMIC);
249
+ }
250
+ presenter.range = textView.selectedRange;
251
+ UIEditMenuConfiguration *configuration =
252
+ [UIEditMenuConfiguration configurationWithIdentifier:nil
253
+ sourcePoint:CGPointMake(CGRectGetMidX(rect), CGRectGetMinY(rect))];
254
+ [presenter.interaction presentEditMenuWithConfiguration:configuration];
255
+ return;
256
+ }
257
+ #pragma clang diagnostic push
258
+ #pragma clang diagnostic ignored "-Wdeprecated-declarations"
259
+ [[UIMenuController sharedMenuController] showMenuFromView:textView rect:rect];
260
+ #pragma clang diagnostic pop
261
+ }
262
+
263
+ static void presentSelectionEditMenuWhenTouchEnds(UITextView *textView, NSRange range, NSUInteger attemptsLeft)
264
+ {
265
+ if (!NSEqualRanges(textView.selectedRange, range)) {
266
+ return;
267
+ }
268
+ if (attemptsLeft > 0 && selectionEditMenuTextViewHasActiveGesture(textView)) {
269
+ __weak UITextView *weakTextView = textView;
270
+ dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(50 * NSEC_PER_MSEC)), dispatch_get_main_queue(), ^{
271
+ UITextView *strongTextView = weakTextView;
272
+ if (strongTextView) {
273
+ presentSelectionEditMenuWhenTouchEnds(strongTextView, range, attemptsLeft - 1);
274
+ }
275
+ });
276
+ return;
277
+ }
278
+ presentSelectionEditMenu(textView);
279
+ }
280
+
281
+ void ENRMSelectRangeAndPresentEditMenu(UITextView *textView, NSRange range)
282
+ {
283
+ [textView becomeFirstResponder];
284
+ textView.selectedRange = range;
285
+ presentSelectionEditMenuWhenTouchEnds(textView, range, 200);
286
+ }
287
+
288
+ void ENRMDismissSelectionEditMenuIfMoved(UITextView *textView)
289
+ {
290
+ if (@available(iOS 16.0, *)) {
291
+ ENRMSelectionEditMenuPresenter *presenter = objc_getAssociatedObject(textView, kSelectionEditMenuPresenterKey);
292
+ if (presenter && !NSEqualRanges(textView.selectedRange, presenter.range)) {
293
+ presenter.range = NSMakeRange(NSNotFound, 0);
294
+ [presenter.interaction dismissMenu];
295
+ }
296
+ }
297
+ }
298
+
122
299
  #endif
@@ -3,6 +3,7 @@
3
3
  #import "CodeBackground.h"
4
4
  #import "ENRMFeatureFlags.h"
5
5
  #import "ENRMImageAttachment.h"
6
+ #import "ENRMLinkChip.h"
6
7
  #import "HighlightRenderer.h"
7
8
  #if ENRICHED_MARKDOWN_MATH
8
9
  #import "ENRMMathInlineAttachment.h"
@@ -460,7 +461,7 @@ static void generateInlineHTML(NSMutableString *html, NSAttributedString *attrib
460
461
  usingBlock:^(NSDictionary<NSAttributedStringKey, id> *attrs, NSRange attrRange, BOOL *stop) {
461
462
  NSString *text = [string substringWithRange:attrRange];
462
463
 
463
- if ([text isEqualToString:@"\n"])
464
+ if ([text isEqualToString:@"\n"] || attrs[ENRMLinkSpacerAttributeName])
464
465
  return;
465
466
 
466
467
  if ([text containsString:kObjectReplacementChar]) {
@@ -0,0 +1,35 @@
1
+ #pragma once
2
+
3
+ #import <Foundation/Foundation.h>
4
+
5
+ #ifdef __cplusplus
6
+ #include <vector>
7
+
8
+ template <typename T>
9
+ static bool ENRMImageRequestHeadersChanged(const std::vector<T> &oldHeaders, const std::vector<T> &newHeaders)
10
+ {
11
+ if (newHeaders.size() != oldHeaders.size()) {
12
+ return true;
13
+ }
14
+ for (size_t i = 0; i < newHeaders.size(); i++) {
15
+ if (newHeaders[i].name != oldHeaders[i].name || newHeaders[i].value != oldHeaders[i].value) {
16
+ return true;
17
+ }
18
+ }
19
+ return false;
20
+ }
21
+
22
+ template <typename T>
23
+ static NSDictionary<NSString *, NSString *> *_Nullable ENRMImageRequestHeadersFromProps(const std::vector<T> &headers)
24
+ {
25
+ if (headers.empty()) {
26
+ return nil;
27
+ }
28
+ NSMutableDictionary<NSString *, NSString *> *result = [NSMutableDictionary dictionaryWithCapacity:headers.size()];
29
+ for (const auto &header : headers) {
30
+ result[@(header.name.c_str())] = @(header.value.c_str());
31
+ }
32
+ return [result copy];
33
+ }
34
+
35
+ #endif
@@ -4,6 +4,7 @@
4
4
  NS_ASSUME_NONNULL_BEGIN
5
5
 
6
6
  static NSString *const CodeBlockAttributeName = @"CodeBlock";
7
+ static NSString *const CodeBlockIndentAttributeName = @"CodeBlockIndent";
7
8
 
8
9
  /**
9
10
  * Returns YES when the last semantic block in the storage is a code block, ignoring any
@@ -5,11 +5,7 @@
5
5
  #import "RenderContext.h"
6
6
  #import "StyleConfig.h"
7
7
 
8
- extern NSString *const ListDepthAttribute;
9
- extern NSString *const ListTypeAttribute;
10
- extern NSString *const ListItemNumberAttribute;
11
- extern NSString *const TaskItemAttribute;
12
- extern NSString *const TaskCheckedAttribute;
8
+ extern NSString *const ListItemMarkerStartAttribute;
13
9
 
14
10
  @implementation ListMarkerDrawer {
15
11
  StyleConfig *_config;
@@ -44,13 +40,13 @@ extern NSString *const TaskCheckedAttribute;
44
40
  if (charRange.location == NSNotFound)
45
41
  return;
46
42
 
47
- // 1. Fetch all attributes at once for efficiency
48
43
  NSDictionary *attrs = [storage attributesAtIndex:charRange.location
49
44
  effectiveRange:NULL];
50
- if (!attrs[ListDepthAttribute])
45
+ NSArray *markers = attrs[ListItemMarkerStartAttribute];
46
+ if (![markers isKindOfClass:[NSArray class]] || markers.count == 0)
51
47
  return;
52
48
 
53
- // 2. Identify the start of the paragraph
49
+ // Identify the start of the paragraph
54
50
  NSRange paraRange = [storage.string paragraphRangeForRange:charRange];
55
51
  if (charRange.location != paraRange.location ||
56
52
  [drawnParagraphs containsObject:@(paraRange.location)])
@@ -61,30 +57,28 @@ extern NSString *const TaskCheckedAttribute;
61
57
 
62
58
  CGPoint glyphLoc = [layoutManager locationForGlyphAtIndex:glyphRange.location];
63
59
  CGFloat baselineY = origin.y + rect.origin.y + glyphLoc.y;
64
- CGFloat markerX;
65
- if (isRTL) {
66
- markerX = origin.x + usedRect.origin.x + usedRect.size.width + gap;
67
- } else {
68
- markerX = origin.x + usedRect.origin.x - gap;
69
- }
70
-
71
- // 4. Draw marker based on type
72
- if ([attrs[TaskItemAttribute] boolValue]) {
73
- UIFont *font = attrs[NSFontAttributeName] ?: [self defaultFont];
74
- BOOL checked = [attrs[TaskCheckedAttribute] boolValue];
75
- const CGFloat size = [_config taskListCheckboxSize];
76
- CGFloat checkboxX = isRTL ? markerX + size / 2.0 : markerX - size / 2.0;
77
- [self drawCheckboxAtX:checkboxX
78
- centerY:baselineY - (font.capHeight / 2.0)
79
- checked:checked];
80
- } else if ([attrs[ListTypeAttribute] integerValue] == ListTypeUnordered) {
81
- UIFont *font = attrs[NSFontAttributeName] ?: [self defaultFont];
82
- NSInteger depth = [attrs[ListDepthAttribute] integerValue];
83
- [self drawBulletAtX:markerX
84
- centerY:baselineY - (font.xHeight + font.capHeight) / 4.0
85
- depth:depth];
86
- } else {
87
- [self drawOrderedMarkerAtX:markerX attrs:attrs baselineY:baselineY isRTL:isRTL];
60
+ UIFont *font = attrs[NSFontAttributeName] ?: [self defaultFont];
61
+
62
+ for (ENRMListMarkerDescriptor *marker in markers) {
63
+ CGFloat markerX = isRTL ? origin.x + container.size.width - marker.indent + gap
64
+ : origin.x + marker.indent - gap;
65
+
66
+ if (marker.isTask) {
67
+ const CGFloat size = [_config taskListCheckboxSize];
68
+ CGFloat checkboxX = isRTL ? markerX + size / 2.0 : markerX - size / 2.0;
69
+ [self drawCheckboxAtX:checkboxX
70
+ centerY:baselineY - (font.capHeight / 2.0)
71
+ checked:marker.isChecked];
72
+ } else if (marker.listType == ListTypeUnordered) {
73
+ [self drawBulletAtX:markerX
74
+ centerY:baselineY - (font.xHeight + font.capHeight) / 4.0
75
+ depth:marker.depth];
76
+ } else {
77
+ [self drawOrderedMarkerAtX:markerX
78
+ number:marker.number
79
+ baselineY:baselineY
80
+ isRTL:isRTL];
81
+ }
88
82
  }
89
83
  }];
90
84
  }
@@ -167,17 +161,10 @@ extern NSString *const TaskCheckedAttribute;
167
161
  y:y];
168
162
  }
169
163
 
170
- - (void)drawOrderedMarkerAtX:(CGFloat)boundaryX
171
- attrs:(NSDictionary *)attrs
172
- baselineY:(CGFloat)baselineY
173
- isRTL:(BOOL)isRTL
164
+ - (void)drawOrderedMarkerAtX:(CGFloat)boundaryX number:(NSInteger)number baselineY:(CGFloat)baselineY isRTL:(BOOL)isRTL
174
165
  {
175
- NSNumber *num = attrs[ListItemNumberAttribute];
176
- if (!num)
177
- return;
178
-
179
- NSString *text = isRTL ? [NSString stringWithFormat:@".%ld", (long)num.integerValue]
180
- : [NSString stringWithFormat:@"%ld.", (long)num.integerValue];
166
+ NSString *text =
167
+ isRTL ? [NSString stringWithFormat:@".%ld", (long)number] : [NSString stringWithFormat:@"%ld.", (long)number];
181
168
  UIFont *font = [_config listMarkerFont] ?: [self defaultFont];
182
169
 
183
170
  NSDictionary *mAttrs = @{NSFontAttributeName : font, NSForegroundColorAttributeName : [_config listStyleMarkerColor]};
@@ -22,6 +22,10 @@ static void serializeNode(MarkdownASTNode *node, NSMutableString *buffer)
22
22
  break;
23
23
 
24
24
  case MarkdownNodeTypeLineBreak:
25
+ [buffer appendString:@"\\\n"];
26
+ break;
27
+
28
+ case MarkdownNodeTypeSoftBreak:
25
29
  [buffer appendString:@"\n"];
26
30
  break;
27
31
 
@@ -2,6 +2,7 @@
2
2
  #import "AccessibilityInfo.h"
3
3
  #import "BlockquoteBorder.h"
4
4
  #import "ENRMAccessibilityLabels.h"
5
+ #import "ENRMLinkChip.h"
5
6
  #include <TargetConditionals.h>
6
7
 
7
8
  typedef NS_ENUM(NSInteger, ElementType) { ElementTypeText, ElementTypeLink, ElementTypeImage };
@@ -113,7 +114,8 @@ static const CGFloat kFocusRectPadding = 2.0;
113
114
  }
114
115
 
115
116
  BOOL isImg = item[@"altText"] != nil;
116
- NSString *label = isImg ? item[@"altText"] : [fullText substringWithRange:itemRange];
117
+ // Link chips pad their text with spacer characters; keep them out of the spoken label.
118
+ NSString *label = isImg ? item[@"altText"] : ENRMPlainTextByRemovingLinkSpacers(textView.attributedText, itemRange);
117
119
  [elements addObject:[self createElementForRange:itemRange
118
120
  type:isImg ? ElementTypeImage : ElementTypeLink
119
121
  text:label
@@ -2,6 +2,7 @@
2
2
  #import "BlockquoteBorder.h"
3
3
  #import "ENRMFeatureFlags.h"
4
4
  #import "ENRMImageAttachment.h"
5
+ #import "ENRMLinkChip.h"
5
6
  #import "ENRMUIKit.h"
6
7
  #import "HighlightRenderer.h"
7
8
  #include <TargetConditionals.h>
@@ -152,7 +153,7 @@ NSString *_Nullable extractMarkdownFromAttributedString(NSAttributedString *attr
152
153
  options:0
153
154
  usingBlock:^(NSDictionary<NSAttributedStringKey, id> *attrs, NSRange attrRange, BOOL *stop) {
154
155
  NSString *text = [[attributedText attributedSubstringFromRange:attrRange] string];
155
- if (text.length == 0)
156
+ if (text.length == 0 || attrs[ENRMLinkSpacerAttributeName])
156
157
  return;
157
158
 
158
159
  // Images and Thematic Breaks
@@ -45,6 +45,11 @@ NSUInteger applyBlockSpacingBefore(NSMutableAttributedString *output, NSUInteger
45
45
  void applyBlockSpacingAfter(NSMutableAttributedString *output, CGFloat marginBottom);
46
46
  void applyLineHeight(NSMutableAttributedString *output, NSRange range, CGFloat lineHeight);
47
47
  void applyBaselineOffset(NSMutableAttributedString *output, NSRange range);
48
+
49
+ /// True when the range contains a block (non-inline) image attachment. Lines holding
50
+ /// such attachments must not be clamped by maximumLineHeight or the image box
51
+ /// overflows the line and paints over surrounding content.
52
+ BOOL ENRMRangeContainsBlockImage(NSAttributedString *output, NSRange range);
48
53
  void applyTextAlignment(NSMutableAttributedString *output, NSRange range, NSTextAlignment textAlign);
49
54
  NSTextAlignment textAlignmentFromString(NSString *textAlign);
50
55
 
@@ -1,5 +1,6 @@
1
1
  #import "ParagraphStyleUtils.h"
2
2
  #import "ENRMFeatureFlags.h"
3
+ #import "ENRMImageAttachment.h"
3
4
  #import "LastElementUtils.h"
4
5
  #import <React/RCTI18nUtil.h>
5
6
 
@@ -246,6 +247,21 @@ void applyBlockSpacingAfter(NSMutableAttributedString *output, CGFloat marginBot
246
247
  [output addAttribute:NSParagraphStyleAttributeName value:spacerStyle range:NSMakeRange(spacerLocation, 1)];
247
248
  }
248
249
 
250
+ BOOL ENRMRangeContainsBlockImage(NSAttributedString *output, NSRange range)
251
+ {
252
+ __block BOOL found = NO;
253
+ [output enumerateAttribute:NSAttachmentAttributeName
254
+ inRange:range
255
+ options:0
256
+ usingBlock:^(id value, __unused NSRange attrRange, BOOL *stop) {
257
+ if ([value isKindOfClass:[ENRMImageAttachment class]] && !((ENRMImageAttachment *)value).isInline) {
258
+ found = YES;
259
+ *stop = YES;
260
+ }
261
+ }];
262
+ return found;
263
+ }
264
+
249
265
  void applyLineHeight(NSMutableAttributedString *output, NSRange range, CGFloat lineHeight)
250
266
  {
251
267
  if (lineHeight <= 0) {
@@ -266,10 +282,12 @@ void applyLineHeight(NSMutableAttributedString *output, NSRange range, CGFloat l
266
282
  }];
267
283
  #endif
268
284
 
285
+ BOOL hasBlockImage = ENRMRangeContainsBlockImage(output, range);
286
+
269
287
  NSMutableParagraphStyle *style = getOrCreateParagraphStyle(output, range.location);
270
288
 
271
289
  style.minimumLineHeight = lineHeight;
272
- style.maximumLineHeight = hasMath ? 0 : lineHeight;
290
+ style.maximumLineHeight = (hasMath || hasBlockImage) ? 0 : lineHeight;
273
291
 
274
292
  [output addAttribute:NSParagraphStyleAttributeName value:style range:range];
275
293
  }
@@ -284,7 +302,8 @@ void applyBaselineOffset(NSMutableAttributedString *output, NSRange range)
284
302
  return;
285
303
  }
286
304
 
287
- __block CGFloat maximumLineHeight = 0;
305
+ // Math paragraphs leave maximumLineHeight at 0, so fall back to minimumLineHeight.
306
+ __block CGFloat targetLineHeight = 0;
288
307
  [output enumerateAttribute:NSParagraphStyleAttributeName
289
308
  inRange:range
290
309
  options:NSAttributedStringEnumerationLongestEffectiveRangeNotRequired
@@ -292,29 +311,59 @@ void applyBaselineOffset(NSMutableAttributedString *output, NSRange range)
292
311
  if (!paragraphStyle) {
293
312
  return;
294
313
  }
295
- maximumLineHeight = MAX(paragraphStyle.maximumLineHeight, maximumLineHeight);
314
+ CGFloat clamp = MAX(paragraphStyle.maximumLineHeight, paragraphStyle.minimumLineHeight);
315
+ targetLineHeight = MAX(clamp, targetLineHeight);
296
316
  }];
297
317
 
298
- if (maximumLineHeight <= 0) {
318
+ if (targetLineHeight <= 0) {
299
319
  return;
300
320
  }
301
321
 
302
- __block CGFloat maximumFontLineHeight = 0;
303
- [output enumerateAttribute:NSFontAttributeName
304
- inRange:range
305
- options:NSAttributedStringEnumerationLongestEffectiveRangeNotRequired
306
- usingBlock:^(UIFont *font, __unused NSRange subrange, __unused BOOL *stop) {
307
- if (!font) {
308
- return;
309
- }
310
- maximumFontLineHeight = MAX(UIFontLineHeight(font), maximumFontLineHeight);
311
- }];
322
+ // Center on real text; on a math-only line center the math box instead of its font.
323
+ __block CGFloat textLineHeight = 0;
324
+ #if ENRICHED_MARKDOWN_MATH
325
+ __block BOOL hasMath = NO;
326
+ #endif
327
+ [output enumerateAttributesInRange:range
328
+ options:0
329
+ usingBlock:^(NSDictionary<NSAttributedStringKey, id> *attrs, __unused NSRange subrange,
330
+ __unused BOOL *stop) {
331
+ #if ENRICHED_MARKDOWN_MATH
332
+ if ([attrs[NSAttachmentAttributeName] isKindOfClass:[ENRMMathInlineAttachment class]]) {
333
+ hasMath = YES;
334
+ return;
335
+ }
336
+ #endif
337
+ UIFont *font = attrs[NSFontAttributeName];
338
+ if (font) {
339
+ textLineHeight = MAX(UIFontLineHeight(font), textLineHeight);
340
+ }
341
+ }];
342
+
343
+ CGFloat contentLineHeight = textLineHeight;
344
+
345
+ #if ENRICHED_MARKDOWN_MATH
346
+ // Math only grows the content height, so measure it (parsing LaTeX) only when text
347
+ // alone wouldn't already fill the line.
348
+ if (hasMath && targetLineHeight > textLineHeight) {
349
+ __block CGFloat mathBoxHeight = 0;
350
+ [output enumerateAttribute:NSAttachmentAttributeName
351
+ inRange:range
352
+ options:0
353
+ usingBlock:^(id value, __unused NSRange subrange, __unused BOOL *stop) {
354
+ if ([value isKindOfClass:[ENRMMathInlineAttachment class]]) {
355
+ mathBoxHeight = MAX(((ENRMMathInlineAttachment *)value).boxHeight, mathBoxHeight);
356
+ }
357
+ }];
358
+ contentLineHeight = MAX(textLineHeight, mathBoxHeight);
359
+ }
360
+ #endif
312
361
 
313
- if (maximumFontLineHeight <= 0 || maximumLineHeight < maximumFontLineHeight) {
362
+ if (contentLineHeight <= 0 || targetLineHeight <= contentLineHeight) {
314
363
  return;
315
364
  }
316
365
 
317
- CGFloat baseLineOffset = (maximumLineHeight - maximumFontLineHeight) / 2.0;
366
+ CGFloat baseLineOffset = (targetLineHeight - contentLineHeight) / 2.0;
318
367
 
319
368
  [output enumerateAttribute:NSBaselineOffsetAttributeName
320
369
  inRange:range
@@ -323,7 +372,18 @@ void applyBaselineOffset(NSMutableAttributedString *output, NSRange range)
323
372
  if (existingOffset != nil) {
324
373
  return;
325
374
  }
326
- [output addAttribute:NSBaselineOffsetAttributeName value:@(baseLineOffset) range:subrange];
375
+ [output enumerateAttribute:NSAttachmentAttributeName
376
+ inRange:subrange
377
+ options:0
378
+ usingBlock:^(id attachment, NSRange attachmentRange, BOOL *innerStop) {
379
+ if ([attachment isKindOfClass:[ENRMImageAttachment class]] &&
380
+ !((ENRMImageAttachment *)attachment).isInline) {
381
+ return;
382
+ }
383
+ [output addAttribute:NSBaselineOffsetAttributeName
384
+ value:@(baseLineOffset)
385
+ range:attachmentRange];
386
+ }];
327
387
  }];
328
388
  }
329
389
 
@@ -1,6 +1,7 @@
1
1
  #import "RTFExportUtils.h"
2
2
  #import "BlockquoteBorder.h"
3
3
  #import "CodeBackground.h"
4
+ #import "ENRMLinkChip.h"
4
5
  #import "LastElementUtils.h"
5
6
  #import "ListItemRenderer.h"
6
7
  #import "RenderContext.h"
@@ -288,6 +289,7 @@ NSAttributedString *prepareAttributedStringForRTFExport(NSAttributedString *attr
288
289
  RCTUIColor *blockquoteBgColor = [styleConfig blockquoteBackgroundColor];
289
290
 
290
291
  processThematicBreaks(prepared);
292
+ ENRMApplyLinkChipBackgroundsAsTextBackground(prepared);
291
293
  processCodes(prepared, codeBgColor);
292
294
  processCodeBlocks(prepared, codeBlockBgColor);
293
295
  processBlockquotes(prepared, blockquoteBgColor);