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

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 (469) hide show
  1. package/README.md +54 -8
  2. package/ReactNativeEnrichedMarkdown.podspec +82 -73
  3. package/android/build.gradle +186 -1
  4. package/android/consumer-rules.pro +1 -1
  5. package/android/generated/java/com/facebook/react/viewmanagers/EnrichedMarkdownManagerDelegate.java +9 -0
  6. package/android/generated/java/com/facebook/react/viewmanagers/EnrichedMarkdownManagerInterface.java +3 -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 +9 -0
  10. package/android/generated/java/com/facebook/react/viewmanagers/EnrichedMarkdownTextManagerInterface.java +3 -0
  11. package/android/generated/jni/react/renderer/components/EnrichedMarkdownTextSpec/EventEmitters.cpp +75 -0
  12. package/android/generated/jni/react/renderer/components/EnrichedMarkdownTextSpec/EventEmitters.h +63 -0
  13. package/android/generated/jni/react/renderer/components/EnrichedMarkdownTextSpec/Props.cpp +35 -0
  14. package/android/generated/jni/react/renderer/components/EnrichedMarkdownTextSpec/Props.h +886 -23
  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 +189 -13
  18. package/android/src/main/java/com/swmansion/enriched/markdown/EnrichedMarkdownInternalText.kt +17 -0
  19. package/android/src/main/java/com/swmansion/enriched/markdown/EnrichedMarkdownManager.kt +50 -0
  20. package/android/src/main/java/com/swmansion/enriched/markdown/EnrichedMarkdownText.kt +48 -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 +42 -0
  23. package/android/src/main/java/com/swmansion/enriched/markdown/MeasurementStore.kt +82 -4
  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/input/EnrichedMarkdownTextInputManager.kt +54 -4
  26. package/android/src/main/java/com/swmansion/enriched/markdown/input/EnrichedMarkdownTextInputView.kt +901 -462
  27. package/android/src/main/java/com/swmansion/enriched/markdown/input/MarkdownClipboard.kt +42 -0
  28. package/android/src/main/java/com/swmansion/enriched/markdown/input/editing/BlockEditCoordinator.kt +196 -0
  29. package/android/src/main/java/com/swmansion/enriched/markdown/input/editing/ClipboardCoordinator.kt +73 -0
  30. package/android/src/main/java/com/swmansion/enriched/markdown/input/editing/EditContext.kt +19 -0
  31. package/android/src/main/java/com/swmansion/enriched/markdown/input/editing/EditPipeline.kt +248 -0
  32. package/android/src/main/java/com/swmansion/enriched/markdown/input/editing/EditSession.kt +52 -0
  33. package/android/src/main/java/com/swmansion/enriched/markdown/input/editing/InputConnectionWrapper.kt +101 -7
  34. package/android/src/main/java/com/swmansion/enriched/markdown/input/editing/LinkCoordinator.kt +69 -0
  35. package/android/src/main/java/com/swmansion/enriched/markdown/input/editing/MarkdownTextWatcher.kt +3 -3
  36. package/android/src/main/java/com/swmansion/enriched/markdown/input/editing/MentionCoordinator.kt +118 -0
  37. package/android/src/main/java/com/swmansion/enriched/markdown/input/events/OnChangeStateEvent.kt +26 -0
  38. package/android/src/main/java/com/swmansion/enriched/markdown/input/events/OnContextMenuItemPressEvent.kt +26 -0
  39. package/android/src/main/java/com/swmansion/enriched/markdown/input/events/OnInputKeyPressEvent.kt +24 -0
  40. package/android/src/main/java/com/swmansion/enriched/markdown/input/events/OnPasteEvent.kt +24 -0
  41. package/android/src/main/java/com/swmansion/enriched/markdown/input/formatting/BlockStore.kt +254 -0
  42. package/android/src/main/java/com/swmansion/enriched/markdown/input/formatting/FormattingStore.kt +80 -87
  43. package/android/src/main/java/com/swmansion/enriched/markdown/input/formatting/InputFormatter.kt +109 -1
  44. package/android/src/main/java/com/swmansion/enriched/markdown/input/formatting/InputParser.kt +116 -22
  45. package/android/src/main/java/com/swmansion/enriched/markdown/input/formatting/MarkdownSerializer.kt +167 -38
  46. package/android/src/main/java/com/swmansion/enriched/markdown/input/formatting/RangeEditAdjustment.kt +149 -0
  47. package/android/src/main/java/com/swmansion/enriched/markdown/input/layout/InputEventEmitter.kt +66 -5
  48. package/android/src/main/java/com/swmansion/enriched/markdown/input/layout/InputMeasurementStore.kt +4 -2
  49. package/android/src/main/java/com/swmansion/enriched/markdown/input/model/BlockRange.kt +27 -0
  50. package/android/src/main/java/com/swmansion/enriched/markdown/input/model/BlockType.kt +48 -0
  51. package/android/src/main/java/com/swmansion/enriched/markdown/input/model/FormattingRange.kt +9 -4
  52. package/android/src/main/java/com/swmansion/enriched/markdown/input/model/InputFormatterStyle.kt +39 -2
  53. package/android/src/main/java/com/swmansion/enriched/markdown/input/model/MathAtom.kt +20 -0
  54. package/android/src/main/java/com/swmansion/enriched/markdown/input/model/MathChipStyle.kt +1 -1
  55. package/android/src/main/java/com/swmansion/enriched/markdown/input/model/MutableRangeBounds.kt +11 -0
  56. package/android/src/main/java/com/swmansion/enriched/markdown/input/spans/InputBulletSpan.kt +82 -0
  57. package/android/src/main/java/com/swmansion/enriched/markdown/input/spans/InputHeadingSpan.kt +58 -0
  58. package/android/src/main/java/com/swmansion/enriched/markdown/input/spans/InputListItemSpacingSpan.kt +37 -0
  59. package/android/src/main/java/com/swmansion/enriched/markdown/input/spans/InputOrderedListMarkerSpan.kt +63 -0
  60. package/android/src/main/java/com/swmansion/enriched/markdown/input/styles/BlockHandler.kt +54 -0
  61. package/android/src/main/java/com/swmansion/enriched/markdown/input/styles/HeadingBlockHandler.kt +27 -0
  62. package/android/src/main/java/com/swmansion/enriched/markdown/input/styles/OrderedListBlockHandler.kt +38 -0
  63. package/android/src/main/java/com/swmansion/enriched/markdown/input/styles/UnorderedListBlockHandler.kt +37 -0
  64. package/android/src/main/java/com/swmansion/enriched/markdown/input/toolbar/InputContextMenu.kt +8 -26
  65. package/android/src/main/java/com/swmansion/enriched/markdown/parser/MarkdownASTNode.kt +1 -0
  66. package/android/src/main/java/com/swmansion/enriched/markdown/parser/Parser.kt +1 -0
  67. package/android/src/main/java/com/swmansion/enriched/markdown/renderer/BlockStyleContext.kt +9 -2
  68. package/android/src/main/java/com/swmansion/enriched/markdown/renderer/BlockquoteRenderer.kt +100 -12
  69. package/android/src/main/java/com/swmansion/enriched/markdown/renderer/CodeBlockRenderer.kt +16 -1
  70. package/android/src/main/java/com/swmansion/enriched/markdown/renderer/HeadingRenderer.kt +4 -0
  71. package/android/src/main/java/com/swmansion/enriched/markdown/renderer/ListContextManager.kt +2 -1
  72. package/android/src/main/java/com/swmansion/enriched/markdown/renderer/ListItemRenderer.kt +74 -18
  73. package/android/src/main/java/com/swmansion/enriched/markdown/renderer/ListRenderer.kt +43 -4
  74. package/android/src/main/java/com/swmansion/enriched/markdown/renderer/NodeRenderer.kt +9 -1
  75. package/android/src/main/java/com/swmansion/enriched/markdown/renderer/SoftBreakRenderer.kt +16 -0
  76. package/android/src/main/java/com/swmansion/enriched/markdown/renderer/SpanStyleCache.kt +30 -27
  77. package/android/src/main/java/com/swmansion/enriched/markdown/spans/BaseListSpan.kt +24 -0
  78. package/android/src/main/java/com/swmansion/enriched/markdown/spans/BlockquoteSpan.kt +174 -24
  79. package/android/src/main/java/com/swmansion/enriched/markdown/spans/CodeBackgroundSpan.kt +27 -3
  80. package/android/src/main/java/com/swmansion/enriched/markdown/spans/CodeBlockSpan.kt +13 -16
  81. package/android/src/main/java/com/swmansion/enriched/markdown/spans/CodeSpan.kt +1 -1
  82. package/android/src/main/java/com/swmansion/enriched/markdown/spans/EmphasisSpan.kt +1 -1
  83. package/android/src/main/java/com/swmansion/enriched/markdown/spans/ImageSpan.kt +182 -46
  84. package/android/src/main/java/com/swmansion/enriched/markdown/spans/ListItemSpacingSpan.kt +33 -0
  85. package/android/src/main/java/com/swmansion/enriched/markdown/spans/ListMarkerAnchorSpan.kt +38 -0
  86. package/android/src/main/java/com/swmansion/enriched/markdown/spans/OrderedListSpan.kt +2 -0
  87. package/android/src/main/java/com/swmansion/enriched/markdown/spans/StrongSpan.kt +1 -1
  88. package/android/src/main/java/com/swmansion/enriched/markdown/spans/TaskListSpan.kt +3 -2
  89. package/android/src/main/java/com/swmansion/enriched/markdown/spans/UnorderedListSpan.kt +3 -2
  90. package/android/src/main/java/com/swmansion/enriched/markdown/styles/BlockquoteStyle.kt +6 -0
  91. package/android/src/main/java/com/swmansion/enriched/markdown/styles/CodeBlockStyle.kt +26 -0
  92. package/android/src/main/java/com/swmansion/enriched/markdown/styles/ImageStyle.kt +7 -1
  93. package/android/src/main/java/com/swmansion/enriched/markdown/styles/ListStyle.kt +4 -1
  94. package/android/src/main/java/com/swmansion/enriched/markdown/styles/StyleConfig.kt +13 -4
  95. package/android/src/main/java/com/swmansion/enriched/markdown/styles/TableStyle.kt +6 -0
  96. package/android/src/main/java/com/swmansion/enriched/markdown/utils/common/CodeBlockHighlighter.kt +90 -0
  97. package/android/src/main/java/com/swmansion/enriched/markdown/utils/common/CodeBlockNode.kt +57 -0
  98. package/android/src/main/java/com/swmansion/enriched/markdown/utils/common/FeatureFlags.kt +1 -0
  99. package/android/src/main/java/com/swmansion/enriched/markdown/utils/common/MarkdownSegment.kt +9 -0
  100. package/android/src/main/java/com/swmansion/enriched/markdown/utils/common/MarkdownViewManagerUtils.kt +37 -7
  101. package/android/src/main/java/com/swmansion/enriched/markdown/utils/common/ReadableMapExtensions.kt +3 -0
  102. package/android/src/main/java/com/swmansion/enriched/markdown/utils/common/RenderedSegment.kt +10 -0
  103. package/android/src/main/java/com/swmansion/enriched/markdown/utils/common/SegmentSignature.kt +1 -0
  104. package/android/src/main/java/com/swmansion/enriched/markdown/utils/common/StreamingMarkdownFilter.kt +83 -5
  105. package/android/src/main/java/com/swmansion/enriched/markdown/utils/common/serialization/MarkdownASTSerializer.kt +4 -0
  106. package/android/src/main/java/com/swmansion/enriched/markdown/utils/input/MarkdownStyleParser.kt +74 -44
  107. package/android/src/main/java/com/swmansion/enriched/markdown/utils/input/PasteTextUtils.kt +20 -0
  108. package/android/src/main/java/com/swmansion/enriched/markdown/utils/text/ImageCache.kt +26 -3
  109. package/android/src/main/java/com/swmansion/enriched/markdown/utils/text/ImageDownloader.kt +22 -9
  110. package/android/src/main/java/com/swmansion/enriched/markdown/utils/text/LocalImageLoader.kt +161 -0
  111. package/android/src/main/java/com/swmansion/enriched/markdown/utils/text/extensions/TextPaintExtensions.kt +23 -0
  112. package/android/src/main/java/com/swmansion/enriched/markdown/utils/text/interaction/CheckboxTouchHelper.kt +7 -0
  113. package/android/src/main/java/com/swmansion/enriched/markdown/utils/text/interaction/TaskListTapUtils.kt +41 -21
  114. package/android/src/main/java/com/swmansion/enriched/markdown/utils/text/span/BlockSpacing.kt +15 -8
  115. package/android/src/main/java/com/swmansion/enriched/markdown/utils/text/view/LinkLongPressMovementMethod.kt +58 -27
  116. package/android/src/main/java/com/swmansion/enriched/markdown/utils/text/view/SelectionActionMode.kt +49 -15
  117. package/android/src/main/java/com/swmansion/enriched/markdown/views/BlockMenuOptions.kt +45 -0
  118. package/android/src/main/java/com/swmansion/enriched/markdown/views/CodeBlockContainerView.kt +396 -0
  119. package/android/src/main/java/com/swmansion/enriched/markdown/views/ContextMenuPopup.kt +9 -6
  120. package/android/src/main/java/com/swmansion/enriched/markdown/views/CopyGlyph.kt +101 -0
  121. package/android/src/main/java/com/swmansion/enriched/markdown/views/TableContainerView.kt +36 -9
  122. package/android/src/main/jni/CMakeLists.txt +53 -0
  123. package/android/src/main/jni/react/renderer/components/EnrichedMarkdownTextSpec/MarkdownContainerShadowNode.cpp +10 -0
  124. package/android/src/main/jni/react/renderer/components/EnrichedMarkdownTextSpec/MarkdownContainerShadowNode.h +11 -2
  125. package/android/src/main/jni/react/renderer/components/EnrichedMarkdownTextSpec/MarkdownTextShadowNode.cpp +10 -0
  126. package/android/src/main/jni/react/renderer/components/EnrichedMarkdownTextSpec/MarkdownTextShadowNode.h +12 -2
  127. package/android/src/main/jni/react/renderer/components/EnrichedMarkdownTextSpec/MarkdownTextState.cpp +9 -0
  128. package/android/src/main/jni/react/renderer/components/EnrichedMarkdownTextSpec/MarkdownTextState.h +24 -0
  129. package/android/src/main/jni/react/renderer/components/EnrichedMarkdownTextSpec/conversions.h +16 -0
  130. package/android/src/math/java/com/swmansion/enriched/markdown/input/math/MathChipControllerImpl.kt +21 -4
  131. package/android/src/math/java/com/swmansion/enriched/markdown/renderer/MathInlineRenderer.kt +7 -2
  132. package/android/src/math/java/com/swmansion/enriched/markdown/spans/MathChipSpan.kt +1 -1
  133. package/android/src/math/java/com/swmansion/enriched/markdown/views/MathContainerView.kt +6 -4
  134. package/cpp/highlight/CodeBlockHighlighter.cpp +284 -0
  135. package/cpp/highlight/CodeBlockHighlighter.hpp +66 -0
  136. package/cpp/highlight/CodeBlockLanguages.cpp +138 -0
  137. package/cpp/highlight/CodeBlockLanguages.hpp +25 -0
  138. package/cpp/highlight/HighlightGrammars.hpp +28 -0
  139. package/cpp/highlight/code_highlight_podspec.rb +211 -0
  140. package/cpp/highlight/gen-registry.mjs +155 -0
  141. package/cpp/highlight/grammar-versions.json +159 -0
  142. package/cpp/highlight/vendor/generated/generated_queries.h +1665 -0
  143. package/cpp/highlight/vendor/generated/generated_registry.cpp +59 -0
  144. package/cpp/parser/MD4CParser.cpp +173 -61
  145. package/cpp/parser/MD4CParser.hpp +1 -0
  146. package/cpp/parser/MarkdownASTNode.hpp +2 -1
  147. package/cpp/wasm/ASTSerializer.cpp +2 -0
  148. package/cpp/wasm/build.sh +1 -0
  149. package/cpp/wasm/md4c_wasm.cpp +3 -1
  150. package/docs/ACCESSIBILITY.md +14 -2
  151. package/docs/API_REFERENCE.md +234 -12
  152. package/docs/BREAKING_CHANGES.md +129 -0
  153. package/docs/CODE_HIGHLIGHT.md +133 -0
  154. package/docs/COPY_OPTIONS.md +47 -3
  155. package/docs/ELEMENTS_STRUCTURE.md +52 -4
  156. package/docs/IMAGE_CACHING.md +30 -0
  157. package/docs/INPUT.md +108 -11
  158. package/docs/LATEX_MATH.md +87 -45
  159. package/docs/MACOS.md +1 -1
  160. package/docs/MARKDOWN_STREAMING.md +27 -1
  161. package/docs/NATIVE_ASSETS.md +127 -0
  162. package/docs/RTL.md +1 -1
  163. package/docs/STYLES.md +46 -6
  164. package/docs/TESTING.md +112 -0
  165. package/docs/TEXT.md +16 -6
  166. package/docs/WEB.md +3 -1
  167. package/ios/EnrichedMarkdown.h +7 -0
  168. package/ios/EnrichedMarkdown.mm +284 -75
  169. package/ios/EnrichedMarkdownText.h +7 -0
  170. package/ios/EnrichedMarkdownText.mm +101 -73
  171. package/ios/attachments/ENRMImageAttachment.h +9 -0
  172. package/ios/attachments/ENRMImageAttachment.m +143 -40
  173. package/ios/attachments/ENRMMathInlineAttachment.h +2 -0
  174. package/ios/attachments/ENRMMathInlineAttachment.m +48 -81
  175. package/ios/attachments/ENRMMathInlineAttachmentShared.h +2 -0
  176. package/ios/generated/ReactCodegen/EnrichedMarkdownTextSpec/EventEmitters.cpp +75 -0
  177. package/ios/generated/ReactCodegen/EnrichedMarkdownTextSpec/EventEmitters.h +63 -0
  178. package/ios/generated/ReactCodegen/EnrichedMarkdownTextSpec/Props.cpp +35 -0
  179. package/ios/generated/ReactCodegen/EnrichedMarkdownTextSpec/Props.h +886 -23
  180. package/ios/generated/ReactCodegen/EnrichedMarkdownTextSpec/RCTComponentViewHelpers.h +131 -0
  181. package/ios/input/ENRMAutoLinkDetector.h +2 -1
  182. package/ios/input/ENRMAutoLinkDetector.mm +79 -41
  183. package/ios/input/ENRMBlockEditCoordinator.h +71 -0
  184. package/ios/input/ENRMBlockEditCoordinator.mm +195 -0
  185. package/ios/input/ENRMBlockRange.h +28 -0
  186. package/ios/input/ENRMBlockRange.mm +30 -0
  187. package/ios/input/ENRMBlockStore.h +56 -0
  188. package/ios/input/ENRMBlockStore.mm +275 -0
  189. package/ios/input/ENRMClipboardCoordinator.h +45 -0
  190. package/ios/input/ENRMClipboardCoordinator.mm +120 -0
  191. package/ios/input/ENRMDetectorPipeline.h +2 -1
  192. package/ios/input/ENRMEditPipeline.h +76 -0
  193. package/ios/input/ENRMEditPipeline.mm +228 -0
  194. package/ios/input/ENRMEditSession.h +36 -0
  195. package/ios/input/ENRMEditSession.mm +63 -0
  196. package/ios/input/ENRMFormattingStore.h +17 -0
  197. package/ios/input/ENRMFormattingStore.mm +95 -105
  198. package/ios/input/ENRMInputBlockType.h +91 -0
  199. package/ios/input/ENRMInputBlockType.mm +5 -0
  200. package/ios/input/ENRMInputDecorationDrawer.h +18 -0
  201. package/ios/input/ENRMInputEventEmitter.h +56 -0
  202. package/ios/input/ENRMInputEventEmitter.mm +308 -0
  203. package/ios/input/ENRMInputFormatter.h +29 -69
  204. package/ios/input/ENRMInputFormatter.mm +216 -124
  205. package/ios/input/ENRMInputFormatterStyle.h +99 -0
  206. package/ios/input/ENRMInputFormatterStyle.mm +188 -0
  207. package/ios/input/ENRMInputLayoutManager.h +9 -0
  208. package/ios/input/ENRMInputLayoutManager.mm +30 -0
  209. package/ios/input/ENRMInputListMarkerDrawer.h +32 -0
  210. package/ios/input/ENRMInputListMarkerDrawer.mm +426 -0
  211. package/ios/input/ENRMInputParser.h +5 -6
  212. package/ios/input/ENRMInputParser.mm +461 -178
  213. package/ios/input/ENRMInputRemend.mm +2 -2
  214. package/ios/input/ENRMInputStyleStateBuilder.h +40 -0
  215. package/ios/input/ENRMInputStyleStateBuilder.mm +60 -0
  216. package/ios/input/ENRMInputTextView.mm +103 -8
  217. package/ios/input/ENRMInputTypingAttributesController.h +42 -0
  218. package/ios/input/ENRMInputTypingAttributesController.mm +203 -0
  219. package/ios/input/ENRMLinkCoordinator.h +41 -0
  220. package/ios/input/ENRMLinkCoordinator.mm +89 -0
  221. package/ios/input/ENRMMarkdownSerializer.h +29 -5
  222. package/ios/input/ENRMMarkdownSerializer.mm +170 -48
  223. package/ios/input/ENRMMathAtom.h +26 -0
  224. package/ios/input/ENRMMathAtom.mm +12 -0
  225. package/ios/input/ENRMMentionCoordinator.h +45 -0
  226. package/ios/input/ENRMMentionCoordinator.mm +167 -0
  227. package/ios/input/ENRMRangeEditAdjustment.h +38 -0
  228. package/ios/input/ENRMRangeEditAdjustment.mm +91 -0
  229. package/ios/input/ENRMRangeStoreUtils.h +39 -0
  230. package/ios/input/EnrichedMarkdownTextInput+ContextMenu.mm +6 -6
  231. package/ios/input/EnrichedMarkdownTextInput+Internal.h +11 -3
  232. package/ios/input/EnrichedMarkdownTextInput.h +7 -1
  233. package/ios/input/EnrichedMarkdownTextInput.mm +1089 -1023
  234. package/ios/input/InputStylePropsUtils.h +109 -68
  235. package/ios/input/internals/EnrichedMarkdownTextInputShadowNode.mm +2 -1
  236. package/ios/input/styles/ENRMBlockHandler.h +46 -0
  237. package/ios/input/styles/ENRMHeadingBlockHandler.h +15 -0
  238. package/ios/input/styles/ENRMHeadingBlockHandler.mm +38 -0
  239. package/ios/input/styles/ENRMOrderedListBlockHandler.h +14 -0
  240. package/ios/input/styles/ENRMOrderedListBlockHandler.mm +48 -0
  241. package/ios/input/styles/ENRMUnorderedListBlockHandler.h +15 -0
  242. package/ios/input/styles/ENRMUnorderedListBlockHandler.mm +51 -0
  243. package/ios/internals/ENRMViewFreeMeasurement.h +331 -0
  244. package/ios/internals/EnrichedMarkdownShadowNode.h +1 -3
  245. package/ios/internals/EnrichedMarkdownShadowNode.mm +16 -20
  246. package/ios/internals/EnrichedMarkdownTextShadowNode.h +1 -3
  247. package/ios/internals/EnrichedMarkdownTextShadowNode.mm +15 -20
  248. package/ios/internals/MeasurementCache.h +33 -7
  249. package/ios/internals/ShadowMeasurementUtils.h +63 -58
  250. package/ios/math/ENRMMathChipController.h +74 -0
  251. package/ios/math/ENRMMathChipController.mm +476 -0
  252. package/ios/math/ENRMRaTeXBridge.swift +4 -1
  253. package/ios/parser/ENRMMarkdownParser.h +1 -8
  254. package/ios/parser/ENRMMarkdownParser.mm +2 -11
  255. package/ios/parser/MarkdownASTNode.h +2 -1
  256. package/ios/parser/MarkdownParserBridge.mm +4 -0
  257. package/ios/renderer/AttributedRenderer.m +20 -2
  258. package/ios/renderer/BaseRenderer.h +17 -2
  259. package/ios/renderer/BaseRenderer.m +30 -0
  260. package/ios/renderer/BlockquoteRenderer.h +1 -1
  261. package/ios/renderer/BlockquoteRenderer.m +144 -35
  262. package/ios/renderer/CodeBlockRenderer.h +1 -1
  263. package/ios/renderer/CodeBlockRenderer.m +27 -23
  264. package/ios/renderer/CodeRenderer.h +1 -1
  265. package/ios/renderer/CodeRenderer.m +3 -1
  266. package/ios/renderer/ENRMImageRenderer.h +1 -1
  267. package/ios/renderer/ENRMImageRenderer.m +5 -1
  268. package/ios/renderer/ENRMMathInlineRenderer.h +1 -1
  269. package/ios/renderer/ENRMMathInlineRenderer.m +5 -1
  270. package/ios/renderer/ENRMSpoilerRenderer.h +1 -1
  271. package/ios/renderer/ENRMSpoilerRenderer.m +3 -1
  272. package/ios/renderer/EmphasisRenderer.h +1 -1
  273. package/ios/renderer/EmphasisRenderer.m +3 -1
  274. package/ios/renderer/HeadingRenderer.h +1 -1
  275. package/ios/renderer/HeadingRenderer.m +13 -6
  276. package/ios/renderer/HighlightRenderer.h +1 -1
  277. package/ios/renderer/HighlightRenderer.m +3 -1
  278. package/ios/renderer/LinkRenderer.h +1 -1
  279. package/ios/renderer/LinkRenderer.m +3 -1
  280. package/ios/renderer/ListItemRenderer.h +13 -1
  281. package/ios/renderer/ListItemRenderer.m +102 -44
  282. package/ios/renderer/ListRenderer.h +2 -2
  283. package/ios/renderer/ListRenderer.m +63 -25
  284. package/ios/renderer/ParagraphRenderer.h +1 -1
  285. package/ios/renderer/ParagraphRenderer.m +16 -8
  286. package/ios/renderer/RenderContext.h +10 -0
  287. package/ios/renderer/RenderContext.m +44 -0
  288. package/ios/renderer/RendererFactory.m +14 -0
  289. package/ios/renderer/StrikethroughRenderer.h +1 -1
  290. package/ios/renderer/StrikethroughRenderer.m +3 -1
  291. package/ios/renderer/StrongRenderer.h +1 -1
  292. package/ios/renderer/StrongRenderer.m +3 -1
  293. package/ios/renderer/SubscriptRenderer.h +1 -1
  294. package/ios/renderer/SubscriptRenderer.m +3 -1
  295. package/ios/renderer/SuperscriptRenderer.h +1 -1
  296. package/ios/renderer/SuperscriptRenderer.m +3 -1
  297. package/ios/renderer/TextRenderer.h +2 -2
  298. package/ios/renderer/TextRenderer.m +3 -1
  299. package/ios/renderer/ThematicBreakRenderer.h +1 -1
  300. package/ios/renderer/ThematicBreakRenderer.m +3 -1
  301. package/ios/renderer/UnderlineRenderer.h +1 -1
  302. package/ios/renderer/UnderlineRenderer.m +3 -1
  303. package/ios/styles/StyleConfig.h +22 -0
  304. package/ios/styles/StyleConfig.mm +132 -0
  305. package/ios/utils/BlockquoteBorder.h +6 -0
  306. package/ios/utils/BlockquoteBorder.m +249 -52
  307. package/ios/utils/CodeBlockBackground.m +16 -2
  308. package/ios/utils/ENRMAtomicSize.h +65 -0
  309. package/ios/utils/ENRMBlockMenu.h +57 -0
  310. package/ios/utils/ENRMCodeBlockContent.h +37 -0
  311. package/ios/utils/ENRMCodeBlockContent.mm +79 -0
  312. package/ios/utils/ENRMCodeBlockHighlighter.h +37 -0
  313. package/ios/utils/ENRMCodeBlockHighlighter.mm +51 -0
  314. package/ios/utils/ENRMFeatureFlags.h +7 -0
  315. package/ios/utils/ENRMImageDownloader.h +11 -1
  316. package/ios/utils/ENRMImageDownloader.m +60 -16
  317. package/ios/utils/ENRMLocalImageLoader.h +31 -0
  318. package/ios/utils/ENRMLocalImageLoader.m +68 -0
  319. package/ios/utils/ENRMMathFallback.h +26 -0
  320. package/ios/utils/ENRMMathFallback.m +18 -0
  321. package/ios/utils/ENRMTextViewSetup.h +35 -17
  322. package/ios/utils/EditMenuUtils.h +22 -5
  323. package/ios/utils/EditMenuUtils.m +53 -9
  324. package/ios/utils/ImageRequestHeaderUtils.h +35 -0
  325. package/ios/utils/LastElementUtils.h +1 -0
  326. package/ios/utils/ListMarkerDrawer.m +29 -42
  327. package/ios/utils/MarkdownASTSerializer.m +4 -0
  328. package/ios/utils/ParagraphStyleUtils.h +5 -0
  329. package/ios/utils/ParagraphStyleUtils.m +77 -17
  330. package/ios/utils/RenderedMarkdownSegment.h +13 -1
  331. package/ios/utils/RenderedMarkdownSegment.m +20 -0
  332. package/ios/utils/SegmentRenderer.m +17 -4
  333. package/ios/utils/StreamingMarkdownFilter.h +11 -1
  334. package/ios/utils/StreamingMarkdownFilter.m +98 -2
  335. package/ios/utils/StylePropsUtils.h +63 -0
  336. package/ios/utils/TaskListTapUtils.m +24 -0
  337. package/ios/views/ENRMCodeBlockContainerView.h +53 -0
  338. package/ios/views/ENRMCodeBlockContainerView.m +559 -0
  339. package/ios/views/ENRMMathContainerView.h +16 -0
  340. package/ios/views/ENRMMathContainerView.m +74 -19
  341. package/ios/views/TableContainerView.h +22 -0
  342. package/ios/views/TableContainerView.m +261 -175
  343. package/jest.d.ts +1 -0
  344. package/jest.js +5 -0
  345. package/lib/module/EnrichedMarkdownNativeComponent.ts +73 -0
  346. package/lib/module/EnrichedMarkdownTextInput.js +84 -5
  347. package/lib/module/EnrichedMarkdownTextInput.js.map +1 -1
  348. package/lib/module/EnrichedMarkdownTextInputNativeComponent.ts +78 -5
  349. package/lib/module/EnrichedMarkdownTextNativeComponent.ts +74 -0
  350. package/lib/module/headingDefaults.js +34 -0
  351. package/lib/module/headingDefaults.js.map +1 -0
  352. package/lib/module/index.js.map +1 -1
  353. package/lib/module/jest/index.js +191 -0
  354. package/lib/module/jest/index.js.map +1 -0
  355. package/lib/module/native/EnrichedMarkdownText.js +37 -5
  356. package/lib/module/native/EnrichedMarkdownText.js.map +1 -1
  357. package/lib/module/normalizeMarkdownStyle.js +81 -19
  358. package/lib/module/normalizeMarkdownStyle.js.map +1 -1
  359. package/lib/module/normalizeMarkdownStyle.web.js +56 -18
  360. package/lib/module/normalizeMarkdownStyle.web.js.map +1 -1
  361. package/lib/module/normalizeMarkdownTextInputStyle.js +62 -15
  362. package/lib/module/normalizeMarkdownTextInputStyle.js.map +1 -1
  363. package/lib/module/normalizeMenuItem.js +1 -1
  364. package/lib/module/utils/textInputState.js +26 -0
  365. package/lib/module/utils/textInputState.js.map +1 -0
  366. package/lib/module/web/EnrichedMarkdownText.js +9 -5
  367. package/lib/module/web/EnrichedMarkdownText.js.map +1 -1
  368. package/lib/module/web/parseMarkdown.js +4 -3
  369. package/lib/module/web/parseMarkdown.js.map +1 -1
  370. package/lib/module/web/renderers/InlineRenderers.js +6 -0
  371. package/lib/module/web/renderers/InlineRenderers.js.map +1 -1
  372. package/lib/module/web/renderers/ListRenderers.js +7 -2
  373. package/lib/module/web/renderers/ListRenderers.js.map +1 -1
  374. package/lib/module/web/renderers/index.js +7 -4
  375. package/lib/module/web/renderers/index.js.map +1 -1
  376. package/lib/module/web/styles.js +83 -6
  377. package/lib/module/web/styles.js.map +1 -1
  378. package/lib/module/web/utils.js +1 -0
  379. package/lib/module/web/utils.js.map +1 -1
  380. package/lib/module/web/wasm/md4c.js +0 -0
  381. package/lib/module/web/wasm/md4c.js.map +1 -1
  382. package/lib/typescript/src/EnrichedMarkdownNativeComponent.d.ts +66 -0
  383. package/lib/typescript/src/EnrichedMarkdownNativeComponent.d.ts.map +1 -1
  384. package/lib/typescript/src/EnrichedMarkdownTextInput.d.ts +94 -9
  385. package/lib/typescript/src/EnrichedMarkdownTextInput.d.ts.map +1 -1
  386. package/lib/typescript/src/EnrichedMarkdownTextInputNativeComponent.d.ts +69 -5
  387. package/lib/typescript/src/EnrichedMarkdownTextInputNativeComponent.d.ts.map +1 -1
  388. package/lib/typescript/src/EnrichedMarkdownTextNativeComponent.d.ts +66 -0
  389. package/lib/typescript/src/EnrichedMarkdownTextNativeComponent.d.ts.map +1 -1
  390. package/lib/typescript/src/headingDefaults.d.ts +9 -0
  391. package/lib/typescript/src/headingDefaults.d.ts.map +1 -0
  392. package/lib/typescript/src/index.d.ts +2 -2
  393. package/lib/typescript/src/index.d.ts.map +1 -1
  394. package/lib/typescript/src/index.web.d.ts +1 -1
  395. package/lib/typescript/src/index.web.d.ts.map +1 -1
  396. package/lib/typescript/src/jest/index.d.ts +6 -0
  397. package/lib/typescript/src/jest/index.d.ts.map +1 -0
  398. package/lib/typescript/src/native/EnrichedMarkdownText.d.ts +3 -3
  399. package/lib/typescript/src/native/EnrichedMarkdownText.d.ts.map +1 -1
  400. package/lib/typescript/src/normalizeMarkdownStyle.d.ts.map +1 -1
  401. package/lib/typescript/src/normalizeMarkdownStyle.web.d.ts.map +1 -1
  402. package/lib/typescript/src/normalizeMarkdownTextInputStyle.d.ts +19 -5
  403. package/lib/typescript/src/normalizeMarkdownTextInputStyle.d.ts.map +1 -1
  404. package/lib/typescript/src/types/MarkdownStyle.d.ts +72 -0
  405. package/lib/typescript/src/types/MarkdownStyle.d.ts.map +1 -1
  406. package/lib/typescript/src/types/MarkdownStyleInternal.d.ts +27 -0
  407. package/lib/typescript/src/types/MarkdownStyleInternal.d.ts.map +1 -1
  408. package/lib/typescript/src/types/MarkdownTextProps.d.ts +104 -9
  409. package/lib/typescript/src/types/MarkdownTextProps.d.ts.map +1 -1
  410. package/lib/typescript/src/types/MarkdownTextProps.web.d.ts +19 -0
  411. package/lib/typescript/src/types/MarkdownTextProps.web.d.ts.map +1 -1
  412. package/lib/typescript/src/types/events.d.ts +19 -0
  413. package/lib/typescript/src/types/events.d.ts.map +1 -1
  414. package/lib/typescript/src/utils/textInputState.d.ts +24 -0
  415. package/lib/typescript/src/utils/textInputState.d.ts.map +1 -0
  416. package/lib/typescript/src/web/EnrichedMarkdownText.d.ts +1 -1
  417. package/lib/typescript/src/web/EnrichedMarkdownText.d.ts.map +1 -1
  418. package/lib/typescript/src/web/parseMarkdown.d.ts +1 -1
  419. package/lib/typescript/src/web/parseMarkdown.d.ts.map +1 -1
  420. package/lib/typescript/src/web/renderers/InlineRenderers.d.ts.map +1 -1
  421. package/lib/typescript/src/web/renderers/ListRenderers.d.ts.map +1 -1
  422. package/lib/typescript/src/web/renderers/index.d.ts +2 -1
  423. package/lib/typescript/src/web/renderers/index.d.ts.map +1 -1
  424. package/lib/typescript/src/web/styles.d.ts +2 -1
  425. package/lib/typescript/src/web/styles.d.ts.map +1 -1
  426. package/lib/typescript/src/web/types.d.ts +6 -2
  427. package/lib/typescript/src/web/types.d.ts.map +1 -1
  428. package/lib/typescript/src/web/utils.d.ts.map +1 -1
  429. package/package.json +36 -9
  430. package/postinstall.mjs +131 -0
  431. package/ratex-version.json +21 -0
  432. package/src/EnrichedMarkdownNativeComponent.ts +73 -0
  433. package/src/EnrichedMarkdownTextInput.tsx +159 -8
  434. package/src/EnrichedMarkdownTextInputNativeComponent.ts +78 -5
  435. package/src/EnrichedMarkdownTextNativeComponent.ts +74 -0
  436. package/src/headingDefaults.ts +21 -0
  437. package/src/index.tsx +9 -0
  438. package/src/index.web.tsx +1 -0
  439. package/src/jest/index.tsx +215 -0
  440. package/src/native/EnrichedMarkdownText.tsx +53 -2
  441. package/src/normalizeMarkdownStyle.ts +102 -16
  442. package/src/normalizeMarkdownStyle.web.ts +63 -15
  443. package/src/normalizeMarkdownTextInputStyle.ts +110 -35
  444. package/src/normalizeMenuItem.ts +1 -1
  445. package/src/types/MarkdownStyle.ts +74 -0
  446. package/src/types/MarkdownStyleInternal.ts +39 -0
  447. package/src/types/MarkdownTextProps.ts +101 -9
  448. package/src/types/MarkdownTextProps.web.ts +19 -0
  449. package/src/types/events.ts +21 -0
  450. package/src/utils/textInputState.ts +35 -0
  451. package/src/web/EnrichedMarkdownText.tsx +16 -2
  452. package/src/web/parseMarkdown.ts +6 -2
  453. package/src/web/renderers/InlineRenderers.tsx +5 -0
  454. package/src/web/renderers/ListRenderers.tsx +14 -2
  455. package/src/web/renderers/index.tsx +6 -2
  456. package/src/web/styles.ts +89 -5
  457. package/src/web/types.ts +6 -1
  458. package/src/web/utils.ts +1 -0
  459. package/src/web/wasm/md4c.js +0 -0
  460. package/vendor-grammars.mjs +511 -0
  461. package/vendor-ratex.mjs +173 -0
  462. package/app.plugin.js +0 -2
  463. package/plugin/build/withAndroidMath.js +0 -19
  464. package/plugin/build/withIosMath.js +0 -28
  465. package/plugin/build/withReactNativeEnrichedMarkdown.js +0 -11
  466. package/plugin/src/withAndroidMath.ts +0 -24
  467. package/plugin/src/withIosMath.ts +0 -35
  468. package/plugin/src/withReactNativeEnrichedMarkdown.ts +0 -17
  469. package/plugin/tsconfig.build.json +0 -16
@@ -2,6 +2,7 @@
2
2
  #import "ContextMenuUtils.h"
3
3
  #import "ENRMAccessibilityLabels.h"
4
4
  #import "ENRMAsyncRenderCoordinator.h"
5
+ #import "ENRMAtomicSize.h"
5
6
  #import "ENRMImageAttachment.h"
6
7
  #import "ENRMMarkdownParser.h"
7
8
  #import "ENRMTailFadeInAnimator.h"
@@ -10,12 +11,14 @@
10
11
  #import "ENRMTextViewSetup.h"
11
12
  #import "ENRMUIKit.h"
12
13
  #import "EditMenuUtils.h"
14
+ #import "ImageRequestHeaderUtils.h"
13
15
 
14
16
  #import "ENRMFeatureFlags.h"
15
17
 
16
18
  #if ENRICHED_MARKDOWN_MATH
17
19
  #import "ENRMMathContainerView.h"
18
20
  #endif
21
+ #import "ENRMCodeBlockContainerView.h"
19
22
  #import "ENRMSpoilerCapable.h"
20
23
  #import "ENRMSpoilerOverlayView.h"
21
24
  #import "ENRMSpoilerTapUtils.h"
@@ -66,10 +69,12 @@ typedef NS_OPTIONS(NSUInteger, ENRMDirtyFlags) {
66
69
 
67
70
  static char kENRMSegmentFadeAnimatorKey;
68
71
 
69
- @interface EnrichedMarkdown () <RCTEnrichedMarkdownViewProtocol, UITextViewDelegate>
72
+ @interface EnrichedMarkdown () <RCTEnrichedMarkdownViewProtocol, UITextViewDelegate, ENRMImageLayoutObserver>
73
+ + (ENRMMd4cFlags *)flagsFromProps:(const EnrichedMarkdownMd4cFlagsStruct &)props;
70
74
  - (void)emitLinkPress:(NSString *)url;
71
75
  - (void)emitLinkLongPress:(NSString *)url;
72
76
  - (void)emitTaskListItemPress:(NSInteger)index checked:(BOOL)checked text:(NSString *)text;
77
+ - (void)emitCopyPress:(NSString *)code language:(NSString *)language;
73
78
  - (void)emitContextMenuItemPress:(NSString *)itemText
74
79
  selectedText:(NSString *)selectedText
75
80
  selectionStart:(NSUInteger)selectionStart
@@ -98,8 +103,13 @@ static char kENRMSegmentFadeAnimatorKey;
98
103
  BOOL _allowTrailingMargin;
99
104
  BOOL _selectable;
100
105
  BOOL _enableLinkPreview;
106
+ BOOL _enableTaskListItemToggle;
107
+ BOOL _contextMenuHidden;
101
108
  BOOL _streamingAnimation;
102
109
  ENRMTableStreamingMode _tableStreamingMode;
110
+ ENRMCodeBlockStreamingMode _codeBlockStreamingMode;
111
+ // Trailing code block whose closing fence hasn't streamed in yet, if any.
112
+ ENRMCodeBlockSegment *_pendingCodeBlockSegment;
103
113
 
104
114
  size_t _renderedStyleFingerprint;
105
115
  size_t _pendingStyleFingerprint;
@@ -116,6 +126,8 @@ static char kENRMSegmentFadeAnimatorKey;
116
126
 
117
127
  ENRMWritingDirectionMode _writingDirectionMode;
118
128
  NSWritingDirection _resolvedLayoutDirection;
129
+
130
+ ENRMAtomicSize _lastCommittedSize;
119
131
  }
120
132
 
121
133
  + (ComponentDescriptorProvider)componentDescriptorProvider
@@ -123,43 +135,16 @@ static char kENRMSegmentFadeAnimatorKey;
123
135
  return concreteComponentDescriptorProvider<EnrichedMarkdownComponentDescriptor>();
124
136
  }
125
137
 
126
- /// Clears every piece of state that `updateProps` derives from props, back to the
127
- /// values the default-constructed `EnrichedMarkdownProps` describes.
128
- ///
129
- /// `updateProps` applies most props as a per-field diff against `_props`, so this
130
- /// state is only correct while it stays in phase with the `_props` baseline it was
131
- /// diffed from. `prepareForRecycle` resets `_props`, so it must reset this too —
132
- /// otherwise every field the next consumer leaves at its default silently inherits
133
- /// the previous consumer's value. Called from `initWithFrame:` as well, so the two
134
- /// baselines cannot drift apart.
135
- ///
136
- /// Requires `_fontScaleObserver` to already exist.
137
- - (void)resetPropDerivedState
138
+ + (ENRMMd4cFlags *)flagsFromProps:(const EnrichedMarkdownMd4cFlagsStruct &)props
138
139
  {
139
- // Discarded rather than cleared field-by-field: the style diff can only clear a
140
- // field when new and old differ, which never holds against a reset baseline.
141
- _config = nil;
142
-
143
- _md4cFlags = [ENRMMd4cFlags propsDefaultFlags];
144
- _maxFontSizeMultiplier = 0;
145
- _allowTrailingMargin = NO;
146
- _fontScaleObserver.allowFontScaling = YES;
147
- _streamingAnimation = NO;
148
- _tableStreamingMode = ENRMTableStreamingModeProgressive;
149
- _spoilerOverlay = ENRMSpoilerOverlayParticles;
150
- _lineBreakStrategy = NSLineBreakStrategyNone;
151
- _writingDirectionMode = ENRMWritingDirectionModeFirstStrong;
152
- _contextMenuItemTexts = nil;
153
- _contextMenuItemIcons = nil;
154
- _accessibilityLabels = nil;
155
-
156
- // Written only once a render completes, so stale until the next one lands.
157
- _renderedStyleFingerprint = 0;
158
- _pendingStyleFingerprint = 0;
159
-
160
- _dirtyFlags = ENRMDirtyNone;
161
- _heightUpdateCounter = 0;
162
- _state = nullptr;
140
+ ENRMMd4cFlags *flags = [ENRMMd4cFlags defaultFlags];
141
+ flags.underline = props.underline;
142
+ flags.superscript = props.superscript;
143
+ flags.subscript = props.subscript;
144
+ flags.latexMath = props.latexMath;
145
+ flags.highlight = props.highlight;
146
+ flags.hardSoftBreaks = props.hardSoftBreaks;
147
+ return flags;
163
148
  }
164
149
 
165
150
  - (instancetype)initWithFrame:(CGRect)frame
@@ -170,22 +155,31 @@ static char kENRMSegmentFadeAnimatorKey;
170
155
 
171
156
  self.backgroundColor = [RCTUIColor clearColor];
172
157
  _parser = [[ENRMMarkdownParser alloc] init];
158
+ _md4cFlags = [EnrichedMarkdown flagsFromProps:defaultProps->md4cFlags];
173
159
  _segmentViews = [NSMutableArray array];
174
160
  _segmentSignatures = [NSMutableArray array];
161
+ _dirtyFlags = ENRMDirtyNone;
175
162
  [self configureSegmentViewRegistry];
176
163
 
177
164
  _renderCoordinator =
178
165
  [[ENRMAsyncRenderCoordinator alloc] initWithQueueLabel:"com.swmansion.enriched.markdown.container.render"];
179
166
 
167
+ _maxFontSizeMultiplier = 0;
168
+ _allowTrailingMargin = NO;
180
169
  _selectable = YES;
181
170
  _enableLinkPreview = YES;
182
- _selectionMenuConfig = (ENRMSelectionMenuConfig){.copyAsMarkdown = YES, .copyImageURL = YES};
171
+ _enableTaskListItemToggle = YES;
172
+ _streamingAnimation = NO;
173
+ _tableStreamingMode = ENRMTableStreamingModeProgressive;
174
+ _codeBlockStreamingMode = ENRMCodeBlockStreamingModeProgressive;
175
+ _contextMenuHidden = NO;
176
+ _selectionMenuConfig = ENRMDefaultSelectionMenuConfig();
177
+ _lineBreakStrategy = NSLineBreakStrategyNone;
178
+ _writingDirectionMode = ENRMWritingDirectionModeFirstStrong;
183
179
  _resolvedLayoutDirection =
184
180
  [[RCTI18nUtil sharedInstance] isRTL] ? NSWritingDirectionRightToLeft : NSWritingDirectionLeftToRight;
185
181
 
186
182
  _fontScaleObserver = [[FontScaleObserver alloc] init];
187
- [self resetPropDerivedState];
188
-
189
183
  __weak EnrichedMarkdown *weakSelf = self;
190
184
  _fontScaleObserver.onChange = ^{
191
185
  EnrichedMarkdown *strongSelf = weakSelf;
@@ -273,6 +267,29 @@ static char kENRMSegmentFadeAnimatorKey;
273
267
  }]];
274
268
  #endif
275
269
 
270
+ [handlers addObject:[ENRMSegmentViewHandler handlerWithKind:ENRMSegmentKindCodeBlock
271
+ matchesView:^BOOL(RCTUIView *view, ENRMRenderedSegment *segment) {
272
+ return [view isKindOfClass:[ENRMCodeBlockContainerView class]];
273
+ }
274
+ createView:^RCTUIView *(ENRMRenderedSegment *segment) {
275
+ EnrichedMarkdown *strongSelf = weakSelf;
276
+ if (!strongSelf) {
277
+ return [[RCTUIView alloc] init];
278
+ }
279
+
280
+ ENRMCodeBlockContainerView *view =
281
+ [strongSelf createCodeBlockViewForSegment:segment.codeBlockSegment];
282
+ [strongSelf animateBlockViewIfNeeded:view];
283
+ return view;
284
+ }
285
+ updateView:^(RCTUIView *view, ENRMRenderedSegment *segment) {
286
+ EnrichedMarkdown *strongSelf = weakSelf;
287
+ ENRMCodeBlockContainerView *codeBlockView = (ENRMCodeBlockContainerView *)view;
288
+ codeBlockView.pending =
289
+ strongSelf && segment.codeBlockSegment == strongSelf->_pendingCodeBlockSegment;
290
+ [codeBlockView applyCodeBlockNode:segment.codeBlockSegment.codeBlockNode];
291
+ }]];
292
+
276
293
  _segmentViewRegistry = [[ENRMSegmentViewRegistry alloc] initWithHandlers:handlers];
277
294
  }
278
295
 
@@ -281,6 +298,29 @@ static char kENRMSegmentFadeAnimatorKey;
281
298
  if (_segmentViews.count == 0)
282
299
  return CGSizeZero;
283
300
 
301
+ if (applyFrames) {
302
+ CGFloat overhang = MAX(_config.tableHorizontalOverflow, 0);
303
+ BOOL needsOverhang = NO;
304
+ if (overhang > 0) {
305
+ for (RCTUIView *seg in _segmentViews) {
306
+ if ([seg isKindOfClass:[TableContainerView class]]) {
307
+ needsOverhang = YES;
308
+ break;
309
+ }
310
+ }
311
+ }
312
+ #if TARGET_OS_OSX
313
+ BOOL isClipping = self.layer.masksToBounds;
314
+ if (isClipping && needsOverhang)
315
+ self.layer.masksToBounds = NO;
316
+ else if (!isClipping && !needsOverhang)
317
+ self.layer.masksToBounds = YES;
318
+ #else
319
+ if (self.clipsToBounds != !needsOverhang)
320
+ self.clipsToBounds = !needsOverhang;
321
+ #endif
322
+ }
323
+
284
324
  __block CGFloat yOffset = 0.0;
285
325
  __block CGFloat maxContentWidth = 0.0;
286
326
  const NSUInteger lastIndex = _segmentViews.count - 1;
@@ -290,6 +330,7 @@ static char kENRMSegmentFadeAnimatorKey;
290
330
  const BOOL shouldAddBottomMargin = (!isLast || _allowTrailingMargin);
291
331
 
292
332
  CGFloat segmentHeight = 0;
333
+ const BOOL isTable = [segment isKindOfClass:[TableContainerView class]];
293
334
 
294
335
  if ([segment isKindOfClass:[EnrichedMarkdownInternalText class]]) {
295
336
  EnrichedMarkdownInternalText *textView = (EnrichedMarkdownInternalText *)segment;
@@ -298,7 +339,7 @@ static char kENRMSegmentFadeAnimatorKey;
298
339
  segmentHeight = textSize.height;
299
340
  maxContentWidth = MAX(maxContentWidth, textSize.width);
300
341
 
301
- } else if ([segment isKindOfClass:[TableContainerView class]]) {
342
+ } else if (isTable) {
302
343
  yOffset += _config.tableMarginTop;
303
344
  segmentHeight = [(TableContainerView *)segment measureHeight:width];
304
345
  maxContentWidth = width;
@@ -310,9 +351,23 @@ static char kENRMSegmentFadeAnimatorKey;
310
351
  maxContentWidth = width;
311
352
  }
312
353
  #endif
354
+ else if ([segment isKindOfClass:[ENRMCodeBlockContainerView class]]) {
355
+ yOffset += _config.codeBlockMarginTop;
356
+ segmentHeight = [(ENRMCodeBlockContainerView *)segment measureHeight:width];
357
+ maxContentWidth = width;
358
+ }
313
359
 
314
360
  if (applyFrames) {
315
- CGRect segmentFrame = CGRectMake(0, yOffset, width, segmentHeight);
361
+ CGFloat segmentX = 0;
362
+ CGFloat segmentWidth = width;
363
+ if (isTable) {
364
+ CGFloat overhang = MAX(_config.tableHorizontalOverflow, 0);
365
+ if (overhang > 0) {
366
+ segmentX = -overhang;
367
+ segmentWidth = width + overhang * 2;
368
+ }
369
+ }
370
+ CGRect segmentFrame = CGRectMake(segmentX, yOffset, segmentWidth, segmentHeight);
316
371
  segment.frame = segmentFrame;
317
372
  #if TARGET_OS_OSX
318
373
  if ([segment isKindOfClass:[EnrichedMarkdownInternalText class]]) {
@@ -335,6 +390,9 @@ static char kENRMSegmentFadeAnimatorKey;
335
390
  yOffset += _config.mathMarginBottom;
336
391
  }
337
392
  #endif
393
+ else if ([segment isKindOfClass:[ENRMCodeBlockContainerView class]] && shouldAddBottomMargin) {
394
+ yOffset += _config.codeBlockMarginBottom;
395
+ }
338
396
  }];
339
397
 
340
398
  return CGSizeMake(maxContentWidth, yOffset);
@@ -353,6 +411,11 @@ static char kENRMSegmentFadeAnimatorKey;
353
411
  return CGSizeMake(measuredWidth, measuredHeight);
354
412
  }
355
413
 
414
+ - (CGSize)lastCommittedLayoutSize
415
+ {
416
+ return _lastCommittedSize.load();
417
+ }
418
+
356
419
  - (BOOL)hasRenderedMarkdown:(NSString *)markdown
357
420
  {
358
421
  return _renderedMarkdown != nil && [_renderedMarkdown isEqualToString:markdown];
@@ -396,6 +459,8 @@ static char kENRMSegmentFadeAnimatorKey;
396
459
  {
397
460
  [super updateLayoutMetrics:layoutMetrics oldLayoutMetrics:oldLayoutMetrics];
398
461
 
462
+ _lastCommittedSize.store(CGSizeMake(layoutMetrics.frame.size.width, layoutMetrics.frame.size.height));
463
+
399
464
  NSWritingDirection resolved = _resolvedLayoutDirection;
400
465
  if (layoutMetrics.layoutDirection == LayoutDirection::RightToLeft) {
401
466
  resolved = NSWritingDirectionRightToLeft;
@@ -440,9 +505,19 @@ static char kENRMSegmentFadeAnimatorKey;
440
505
  }
441
506
  }
442
507
 
443
- // Table and math views cache the copy labels at creation time, so re-push them
444
- // on prop updates (e.g. a language change without a remount) to avoid stale
445
- // labels. Only the copy/copy-as-markdown labels apply to these block menus.
508
+ - (ENRMBlockMenuOptions)blockMenuOptions
509
+ {
510
+ return (ENRMBlockMenuOptions){
511
+ .copyHidden = !_selectionMenuConfig.copyEnabled,
512
+ .copyWritesMarkdown = _selectionMenuConfig.copyFormatMarkdown,
513
+ .copyAsMarkdownHidden = !_selectionMenuConfig.copyAsMarkdown,
514
+ .copyButtonHidden = !_selectionMenuConfig.codeBlockCopyButton,
515
+ };
516
+ }
517
+
518
+ // Table, math and code block views cache the copy labels and menu options at
519
+ // creation time, so re-push them on prop updates (e.g. a language change
520
+ // without a remount) to avoid stale values.
446
521
  - (void)pushSelectionMenuLabelsToSegments
447
522
  {
448
523
  for (RCTUIView *segment in _segmentViews) {
@@ -450,14 +525,25 @@ static char kENRMSegmentFadeAnimatorKey;
450
525
  TableContainerView *tableView = (TableContainerView *)segment;
451
526
  tableView.copyLabel = _selectionMenuLabels.copyLabel;
452
527
  tableView.copyAsMarkdownLabel = _selectionMenuLabels.copyAsMarkdownLabel;
528
+ tableView.contextMenuHidden = _contextMenuHidden;
529
+ tableView.menuOptions = [self blockMenuOptions];
453
530
  }
454
531
  #if ENRICHED_MARKDOWN_MATH
455
532
  else if ([segment isKindOfClass:[ENRMMathContainerView class]]) {
456
533
  ENRMMathContainerView *mathView = (ENRMMathContainerView *)segment;
457
534
  mathView.copyLabel = _selectionMenuLabels.copyLabel;
458
535
  mathView.copyAsMarkdownLabel = _selectionMenuLabels.copyAsMarkdownLabel;
536
+ mathView.contextMenuHidden = _contextMenuHidden;
537
+ mathView.menuOptions = [self blockMenuOptions];
459
538
  }
460
539
  #endif
540
+ else if ([segment isKindOfClass:[ENRMCodeBlockContainerView class]]) {
541
+ ENRMCodeBlockContainerView *codeBlockView = (ENRMCodeBlockContainerView *)segment;
542
+ codeBlockView.copyLabel = _selectionMenuLabels.copyLabel;
543
+ codeBlockView.copyAsMarkdownLabel = _selectionMenuLabels.copyAsMarkdownLabel;
544
+ codeBlockView.contextMenuHidden = _contextMenuHidden;
545
+ codeBlockView.menuOptions = [self blockMenuOptions];
546
+ }
461
547
  }
462
548
  }
463
549
 
@@ -466,6 +552,25 @@ static char kENRMSegmentFadeAnimatorKey;
466
552
  ENRMRequestHeightUpdate<EnrichedMarkdownState>(_state, _heightUpdateCounter, self);
467
553
  }
468
554
 
555
+ // A block image in one of the text segments resolved its box height after
556
+ // loading (maxHeight/aspectRatio sizing). The shadow node measured — and
557
+ // cached — this markdown with the pre-load fallback height, so drop those
558
+ // entries, re-stack segments, and re-measure.
559
+ - (void)imageAttachmentDidResolveLayout
560
+ {
561
+ if (_renderedMarkdown.length > 0) {
562
+ MeasurementCache::shared().removeMatchingMarkdown(std::string(_renderedMarkdown.UTF8String));
563
+ }
564
+
565
+ if (self.bounds.size.width > 0) {
566
+ [self setNeedsLayout];
567
+ CGSize measured = [self measureSize:self.bounds.size.width];
568
+ if (needsHeightUpdate(measured, self.bounds)) {
569
+ [self requestHeightUpdate];
570
+ }
571
+ }
572
+ }
573
+
469
574
  - (void)renderMarkdownContent:(NSString *)markdownString
470
575
  {
471
576
  if (_renderCoordinator.blockAsyncRender)
@@ -482,17 +587,21 @@ static char kENRMSegmentFadeAnimatorKey;
482
587
  BOOL allowTrailingMargin = _allowTrailingMargin;
483
588
  BOOL streamingAnimation = _streamingAnimation;
484
589
  ENRMTableStreamingMode tableStreamingMode = _tableStreamingMode;
590
+ ENRMCodeBlockStreamingMode codeBlockStreamingMode = _codeBlockStreamingMode;
485
591
  NSLineBreakStrategy lineBreakStrategy = _lineBreakStrategy;
486
592
  ENRMWritingDirectionMode writingDirectionMode = _writingDirectionMode;
487
593
  NSWritingDirection resolvedLayoutDirection = _resolvedLayoutDirection;
488
594
 
489
595
  __block NSArray<ENRMRenderedSegment *> *renderedSegments = nil;
490
596
  __block NSString *renderableMarkdown = nil;
597
+ __block BOOL endsInsideOpenCodeFence = NO;
491
598
 
492
599
  [_renderCoordinator
493
600
  scheduleRender:^BOOL {
494
- renderableMarkdown = streamingAnimation ? ENRMRenderableMarkdownForStreaming(markdownString, tableStreamingMode)
495
- : markdownString;
601
+ renderableMarkdown = streamingAnimation
602
+ ? ENRMRenderableMarkdownForStreaming(markdownString, tableStreamingMode,
603
+ codeBlockStreamingMode, &endsInsideOpenCodeFence)
604
+ : markdownString;
496
605
 
497
606
  if (renderableMarkdown.length == 0) {
498
607
  renderedSegments = @[];
@@ -515,7 +624,9 @@ static char kENRMSegmentFadeAnimatorKey;
515
624
  }
516
625
  apply:^{
517
626
  self->_renderedStyleFingerprint = self->_pendingStyleFingerprint;
518
- [self applyRenderedSegments:renderedSegments renderedMarkdown:renderableMarkdown];
627
+ [self applyRenderedSegments:renderedSegments
628
+ renderedMarkdown:renderableMarkdown
629
+ endsInsideOpenCodeFence:endsInsideOpenCodeFence];
519
630
  }];
520
631
  }
521
632
 
@@ -552,8 +663,11 @@ static char kENRMSegmentFadeAnimatorKey;
552
663
 
553
664
  _renderCoordinator.blockAsyncRender = YES;
554
665
  _cachedMarkdown = [markdownString copy];
666
+ BOOL endsInsideOpenCodeFence = NO;
555
667
  NSString *renderableMarkdown =
556
- _streamingAnimation ? ENRMRenderableMarkdownForStreaming(markdownString, _tableStreamingMode) : markdownString;
668
+ _streamingAnimation ? ENRMRenderableMarkdownForStreaming(markdownString, _tableStreamingMode,
669
+ _codeBlockStreamingMode, &endsInsideOpenCodeFence)
670
+ : markdownString;
557
671
  _renderedMarkdown = [renderableMarkdown copy];
558
672
  _renderedStyleFingerprint = _pendingStyleFingerprint;
559
673
 
@@ -566,6 +680,8 @@ static char kENRMSegmentFadeAnimatorKey;
566
680
  return;
567
681
  }
568
682
 
683
+ [self updatePendingCodeBlockSegment:endsInsideOpenCodeFence segments:renderedSegments];
684
+
569
685
  for (ENRMRenderedSegment *segment in renderedSegments) {
570
686
  RCTUIView *view = [_segmentViewRegistry createViewForSegment:segment];
571
687
  [_segmentViews addObject:view];
@@ -574,9 +690,24 @@ static char kENRMSegmentFadeAnimatorKey;
574
690
  }
575
691
  }
576
692
 
577
- - (void)applyRenderedSegments:(NSArray *)renderedSegments renderedMarkdown:(NSString *)renderedMarkdown
693
+ - (void)updatePendingCodeBlockSegment:(BOOL)endsInsideOpenCodeFence segments:(NSArray<ENRMRenderedSegment *> *)segments
694
+ {
695
+ _pendingCodeBlockSegment = nil;
696
+ if (!_streamingAnimation || !endsInsideOpenCodeFence) {
697
+ return;
698
+ }
699
+ ENRMRenderedSegment *last = segments.lastObject;
700
+ if (last.kind == ENRMSegmentKindCodeBlock) {
701
+ _pendingCodeBlockSegment = last.codeBlockSegment;
702
+ }
703
+ }
704
+
705
+ - (void)applyRenderedSegments:(NSArray *)renderedSegments
706
+ renderedMarkdown:(NSString *)renderedMarkdown
707
+ endsInsideOpenCodeFence:(BOOL)endsInsideOpenCodeFence
578
708
  {
579
709
  _renderedMarkdown = [renderedMarkdown copy];
710
+ [self updatePendingCodeBlockSegment:endsInsideOpenCodeFence segments:renderedSegments];
580
711
  BOOL segmentTopologyChanged = _streamingAnimation && [self renderedSegmentsChangeTopology:renderedSegments];
581
712
 
582
713
  ENRMSegmentReconciliationResult *result = [ENRMSegmentReconciler reconcileCurrentViews:_segmentViews
@@ -600,6 +731,15 @@ static char kENRMSegmentFadeAnimatorKey;
600
731
  _segmentViews = result.views;
601
732
  _segmentSignatures = result.signatures;
602
733
 
734
+ // A just-closed block has unchanged content, so the reconciler reuses it
735
+ // without an update; sync pending here to trigger its deferred highlight.
736
+ [_segmentViews enumerateObjectsUsingBlock:^(RCTUIView *segment, NSUInteger i, BOOL *stop) {
737
+ if ([segment isKindOfClass:[ENRMCodeBlockContainerView class]]) {
738
+ ((ENRMCodeBlockContainerView *)segment).pending =
739
+ self->_pendingCodeBlockSegment != nil && i == self->_segmentViews.count - 1;
740
+ }
741
+ }];
742
+
603
743
  if (self.bounds.size.width > 0) {
604
744
  [self setNeedsLayout];
605
745
 
@@ -647,6 +787,9 @@ static char kENRMSegmentFadeAnimatorKey;
647
787
  if (!strongSelf) {
648
788
  return baseMenu;
649
789
  }
790
+ if (strongSelf->_contextMenuHidden) {
791
+ return nil;
792
+ }
650
793
  NSString *segmentMarkdown = extractMarkdownFromAttributedString(textView.textStorage, textView.selectedRange);
651
794
  NSArray<NSMenuItem *> *customItems = ENRMBuildContextMenuItems(
652
795
  strongSelf->_contextMenuItemTexts, strongSelf->_contextMenuItemIcons, textView,
@@ -657,7 +800,7 @@ static char kENRMSegmentFadeAnimatorKey;
657
800
  selectionEnd:selectionEnd];
658
801
  });
659
802
  return buildEditMenuForSelection(textView.textStorage, textView.selectedRange, segmentMarkdown, strongSelf->_config,
660
- @[ baseMenu ], customItems, strongSelf->_selectionMenuConfig);
803
+ @[ baseMenu ], customItems, strongSelf -> _selectionMenuConfig);
661
804
  }];
662
805
  #endif
663
806
 
@@ -676,6 +819,8 @@ static char kENRMSegmentFadeAnimatorKey;
676
819
  tableView.accessibilityLabels = _accessibilityLabels;
677
820
  tableView.copyLabel = _selectionMenuLabels.copyLabel;
678
821
  tableView.copyAsMarkdownLabel = _selectionMenuLabels.copyAsMarkdownLabel;
822
+ tableView.contextMenuHidden = _contextMenuHidden;
823
+ tableView.menuOptions = [self blockMenuOptions];
679
824
 
680
825
  __weak EnrichedMarkdown *weakSelf = self;
681
826
 
@@ -715,11 +860,33 @@ static char kENRMSegmentFadeAnimatorKey;
715
860
  mathView.accessibilityLabels = _accessibilityLabels;
716
861
  mathView.copyLabel = _selectionMenuLabels.copyLabel;
717
862
  mathView.copyAsMarkdownLabel = _selectionMenuLabels.copyAsMarkdownLabel;
863
+ mathView.contextMenuHidden = _contextMenuHidden;
864
+ mathView.menuOptions = [self blockMenuOptions];
718
865
  [mathView applyLatex:mathSegment.latex];
719
866
  return mathView;
720
867
  }
721
868
  #endif
722
869
 
870
+ - (ENRMCodeBlockContainerView *)createCodeBlockViewForSegment:(ENRMCodeBlockSegment *)codeBlockSegment
871
+ {
872
+ ENRMCodeBlockContainerView *codeBlockView = [[ENRMCodeBlockContainerView alloc] initWithConfig:_config];
873
+ codeBlockView.copyLabel = _selectionMenuLabels.copyLabel;
874
+ codeBlockView.copyAsMarkdownLabel = _selectionMenuLabels.copyAsMarkdownLabel;
875
+ codeBlockView.contextMenuHidden = _contextMenuHidden;
876
+ codeBlockView.menuOptions = [self blockMenuOptions];
877
+
878
+ __weak EnrichedMarkdown *weakSelf = self;
879
+ codeBlockView.onCopyPress = ^(NSString *code, NSString *language) {
880
+ EnrichedMarkdown *strongSelf = weakSelf;
881
+ if (strongSelf)
882
+ [strongSelf emitCopyPress:code language:language];
883
+ };
884
+
885
+ codeBlockView.pending = codeBlockSegment == _pendingCodeBlockSegment;
886
+ [codeBlockView applyCodeBlockNode:codeBlockSegment.codeBlockNode];
887
+ return codeBlockView;
888
+ }
889
+
723
890
  - (void)animateBlockViewIfNeeded:(RCTUIView *)view
724
891
  {
725
892
  if (!_streamingAnimation)
@@ -784,6 +951,14 @@ static char kENRMSegmentFadeAnimatorKey;
784
951
  }
785
952
  }
786
953
 
954
+ if (ENRMImageRequestHeadersChanged(oldViewProps.imageRequestHeaders, newViewProps.imageRequestHeaders)) {
955
+ [_config setImageRequestHeaders:ENRMImageRequestHeadersFromProps(newViewProps.imageRequestHeaders)];
956
+ _dirtyFlags |= ENRMDirtyRender;
957
+ if (!markdownChanged) {
958
+ _dirtyFlags |= ENRMDirtyRecreateSegments;
959
+ }
960
+ }
961
+
787
962
  _selectable = newViewProps.selectable;
788
963
 
789
964
  for (RCTUIView *segment in _segmentViews) {
@@ -816,28 +991,19 @@ static char kENRMSegmentFadeAnimatorKey;
816
991
  _dirtyFlags |= ENRMDirtyRecreateSegments | ENRMDirtyForceHeight | ENRMDirtyRender;
817
992
  }
818
993
 
819
- if (newViewProps.md4cFlags.underline != oldViewProps.md4cFlags.underline) {
820
- _md4cFlags.underline = newViewProps.md4cFlags.underline;
821
- _dirtyFlags |= ENRMDirtyForceHeight | ENRMDirtyRender;
822
- }
823
- if (newViewProps.md4cFlags.superscript != oldViewProps.md4cFlags.superscript) {
824
- _md4cFlags.superscript = newViewProps.md4cFlags.superscript;
825
- _dirtyFlags |= ENRMDirtyForceHeight | ENRMDirtyRender;
826
- }
827
- if (newViewProps.md4cFlags.subscript != oldViewProps.md4cFlags.subscript) {
828
- _md4cFlags.subscript = newViewProps.md4cFlags.subscript;
829
- _dirtyFlags |= ENRMDirtyForceHeight | ENRMDirtyRender;
830
- }
831
- if (newViewProps.md4cFlags.latexMath != oldViewProps.md4cFlags.latexMath) {
832
- _md4cFlags.latexMath = newViewProps.md4cFlags.latexMath;
833
- _dirtyFlags |= ENRMDirtyForceHeight | ENRMDirtyRender;
834
- }
835
- if (newViewProps.md4cFlags.highlight != oldViewProps.md4cFlags.highlight) {
836
- _md4cFlags.highlight = newViewProps.md4cFlags.highlight;
994
+ if (newViewProps.md4cFlags.underline != oldViewProps.md4cFlags.underline ||
995
+ newViewProps.md4cFlags.superscript != oldViewProps.md4cFlags.superscript ||
996
+ newViewProps.md4cFlags.subscript != oldViewProps.md4cFlags.subscript ||
997
+ newViewProps.md4cFlags.latexMath != oldViewProps.md4cFlags.latexMath ||
998
+ newViewProps.md4cFlags.highlight != oldViewProps.md4cFlags.highlight ||
999
+ newViewProps.md4cFlags.hardSoftBreaks != oldViewProps.md4cFlags.hardSoftBreaks) {
1000
+ _md4cFlags = [EnrichedMarkdown flagsFromProps:newViewProps.md4cFlags];
837
1001
  _dirtyFlags |= ENRMDirtyForceHeight | ENRMDirtyRender;
838
1002
  }
839
1003
 
840
1004
  _enableLinkPreview = newViewProps.enableLinkPreview;
1005
+ _enableTaskListItemToggle = newViewProps.enableTaskListItemToggle;
1006
+ _contextMenuHidden = newViewProps.contextMenuHidden;
841
1007
 
842
1008
  if (newViewProps.streamingAnimation != oldViewProps.streamingAnimation) {
843
1009
  _streamingAnimation = newViewProps.streamingAnimation;
@@ -862,15 +1028,21 @@ static char kENRMSegmentFadeAnimatorKey;
862
1028
  _dirtyFlags |= ENRMDirtyForceHeight | ENRMDirtyRender;
863
1029
  }
864
1030
 
1031
+ if (newViewProps.streamingConfig.codeBlockMode != oldViewProps.streamingConfig.codeBlockMode) {
1032
+ NSString *codeBlockModeStr =
1033
+ [[NSString alloc] initWithUTF8String:newViewProps.streamingConfig.codeBlockMode.c_str()];
1034
+ _codeBlockStreamingMode = [codeBlockModeStr isEqualToString:@"hidden"] ? ENRMCodeBlockStreamingModeHidden
1035
+ : ENRMCodeBlockStreamingModeProgressive;
1036
+ _dirtyFlags |= ENRMDirtyForceHeight | ENRMDirtyRender;
1037
+ }
1038
+
865
1039
  if (ENRMContextMenuItemsChanged(oldViewProps.contextMenuItems, newViewProps.contextMenuItems)) {
866
1040
  _contextMenuItemTexts = ENRMContextMenuTextsFromItems(newViewProps.contextMenuItems);
867
1041
  _contextMenuItemIcons = ENRMContextMenuIconsFromItems(newViewProps.contextMenuItems);
868
1042
  }
869
1043
 
870
1044
  _selectionMenuLabels = ENRMParseSelectionMenuLabels(newViewProps.selectionMenuConfig);
871
- _selectionMenuConfig =
872
- ENRMBuildSelectionMenuConfig(_selectionMenuLabels, newViewProps.selectionMenuConfig.copyAsMarkdown,
873
- newViewProps.selectionMenuConfig.copyImageUrl);
1045
+ _selectionMenuConfig = ENRMBuildSelectionMenuConfig(_selectionMenuLabels, newViewProps.selectionMenuConfig);
874
1046
  [self pushSelectionMenuLabelsToSegments];
875
1047
 
876
1048
  if (ENRMAccessibilityLabelsChanged(oldViewProps.accessibilityLabels, newViewProps.accessibilityLabels)) {
@@ -964,7 +1136,8 @@ static char kENRMSegmentFadeAnimatorKey;
964
1136
 
965
1137
  - (void)prepareForRecycle
966
1138
  {
967
- _props = std::make_shared<const EnrichedMarkdownProps>();
1139
+ const auto resetProps = std::make_shared<const EnrichedMarkdownProps>();
1140
+ _props = resetProps;
968
1141
  [_renderCoordinator invalidate];
969
1142
 
970
1143
  for (RCTUIView *segment in _segmentViews) {
@@ -982,8 +1155,31 @@ static char kENRMSegmentFadeAnimatorKey;
982
1155
 
983
1156
  _cachedMarkdown = nil;
984
1157
  _renderedMarkdown = nil;
1158
+ _config = nil;
1159
+ _md4cFlags = [EnrichedMarkdown flagsFromProps:resetProps->md4cFlags];
1160
+ _maxFontSizeMultiplier = 0;
1161
+ _allowTrailingMargin = NO;
1162
+ _streamingAnimation = NO;
1163
+ _tableStreamingMode = ENRMTableStreamingModeProgressive;
1164
+ _codeBlockStreamingMode = ENRMCodeBlockStreamingModeProgressive;
1165
+ _pendingCodeBlockSegment = nil;
1166
+ _lineBreakStrategy = NSLineBreakStrategyNone;
1167
+ _writingDirectionMode = ENRMWritingDirectionModeFirstStrong;
1168
+ _renderedStyleFingerprint = 0;
1169
+ _pendingStyleFingerprint = 0;
1170
+ _contextMenuItemTexts = nil;
1171
+ _contextMenuItemIcons = nil;
1172
+ _fontScaleObserver.allowFontScaling = resetProps->allowFontScaling;
1173
+ _accessibilityLabels = nil;
1174
+ _spoilerOverlay =
1175
+ ENRMSpoilerOverlayFromString([[NSString alloc] initWithUTF8String:resetProps->spoilerOverlay.c_str()]);
1176
+ _dirtyFlags = ENRMDirtyNone;
985
1177
 
986
- [self resetPropDerivedState];
1178
+ // Ported from the fork's resetPropDerivedState: upstream's prepareForRecycle covers every
1179
+ // other prop-derived ivar but leaves these two, so a recycled view keeps the previous
1180
+ // consumer's height-update counter and a dangling shadow-node state handle.
1181
+ _heightUpdateCounter = 0;
1182
+ _state = nullptr;
987
1183
 
988
1184
  [super prepareForRecycle];
989
1185
  }
@@ -1084,6 +1280,14 @@ Class<RCTComponentViewProtocol> EnrichedMarkdownCls(void)
1084
1280
  emitter->onTaskListItemPress({.index = (int)index, .checked = checked, .text = std::string(text.UTF8String ?: "")});
1085
1281
  }
1086
1282
 
1283
+ - (void)emitCopyPress:(NSString *)code language:(NSString *)language
1284
+ {
1285
+ auto emitter = std::static_pointer_cast<EnrichedMarkdownEventEmitter const>(_eventEmitter);
1286
+ if (emitter)
1287
+ emitter->onCopyPress(
1288
+ {.code = std::string(code.UTF8String ?: ""), .language = std::string(language.UTF8String ?: "")});
1289
+ }
1290
+
1087
1291
  - (void)emitContextMenuItemPress:(NSString *)itemText
1088
1292
  selectedText:(NSString *)selectedText
1089
1293
  selectionStart:(NSUInteger)selectionStart
@@ -1103,7 +1307,8 @@ Class<RCTComponentViewProtocol> EnrichedMarkdownCls(void)
1103
1307
  {
1104
1308
  ENRMPlatformTextView *textView = (ENRMPlatformTextView *)recognizer.view;
1105
1309
 
1106
- if (handleTaskListTapWithSharedLogic(
1310
+ if (_enableTaskListItemToggle &&
1311
+ handleTaskListTapWithSharedLogic(
1107
1312
  textView, recognizer, &self->_cachedMarkdown, self->_config,
1108
1313
  ^(NSInteger index, BOOL checked, NSString *itemText) {
1109
1314
  [self emitTaskListItemPress:index checked:checked text:itemText];
@@ -1132,6 +1337,10 @@ Class<RCTComponentViewProtocol> EnrichedMarkdownCls(void)
1132
1337
  editMenuForTextInRange:(NSRange)range
1133
1338
  suggestedActions:(NSArray<UIMenuElement *> *)suggestedActions API_AVAILABLE(ios(16.0))
1134
1339
  {
1340
+ if (_contextMenuHidden) {
1341
+ return nil;
1342
+ }
1343
+
1135
1344
  __weak EnrichedMarkdown *weakSelf = self;
1136
1345
  ENRMContextMenuPressHandler handler =
1137
1346
  ^(NSString *itemText, NSString *selectedText, NSUInteger selectionStart, NSUInteger selectionEnd) {
@@ -13,6 +13,13 @@ NS_ASSUME_NONNULL_BEGIN
13
13
  - (void)renderMarkdownSynchronously:(NSString *)markdownString;
14
14
  - (BOOL)hasRenderedMarkdown:(NSString *)markdown;
15
15
  - (BOOL)hasRenderedWithStyleFingerprint:(size_t)fingerprint;
16
+
17
+ /// Size last committed by Fabric via `updateLayoutMetrics:`, readable from
18
+ /// any thread without blocking (issue #550: the shadow-node measure path must
19
+ /// never wait on the main thread, and reading `bounds` off-main is unsafe).
20
+ /// Backed by a single lock-free atomic, so the pair can't tear. Returns
21
+ /// CGSizeZero until the first layout is committed.
22
+ - (CGSize)lastCommittedLayoutSize;
16
23
  @end
17
24
 
18
25
  NS_ASSUME_NONNULL_END