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
@@ -5,6 +5,7 @@ import type {
5
5
  LinkPressEvent,
6
6
  LinkLongPressEvent,
7
7
  TaskListItemPressEvent,
8
+ CopyPressEvent,
8
9
  } from './events';
9
10
 
10
11
  /**
@@ -56,22 +57,31 @@ export interface SelectionMenuPluralLabels {
56
57
  * Controls the built-in items added to the native text selection menu and
57
58
  * lets you localize their labels.
58
59
  *
59
- * Each item accepts an object: `{ enabled }` toggles visibility (the system
60
- * `copy` item can't be hidden — only relabeled) and `label` overrides the
61
- * English default. Wire `label` to your i18n library to match the rest of your
62
- * app's UI. Labels apply to the main text selection menu as well as the table
63
- * and math block copy menus.
60
+ * Each item accepts an object: `{ enabled }` toggles visibility and `label`
61
+ * overrides the English default. Wire `label` to your i18n library to match
62
+ * the rest of your app's UI. Items and labels apply to the main text selection
63
+ * menu as well as the table, math and code block copy menus.
64
+ *
65
+ * `copy.enabled`, `copy.format` and `systemItems` are ignored on macOS.
64
66
  *
65
67
  * @platform ios, android, macos
66
68
  */
67
69
  export interface SelectionMenuConfig {
68
70
  /**
69
- * The system "Copy" item. It can't be hidden — only its label is configurable.
70
- * @default { label: "Copy" }
71
+ * The "Copy" item.
72
+ * - `enabled`: `false` removes it from the text selection menu, the table /
73
+ * math / code block menus and the code block VoiceOver copy action.
74
+ * - `format`: `'rich'` copies rich text (plain + HTML, plus RTF on iOS) from
75
+ * text selections and the raw content from blocks; `'markdown'` copies
76
+ * Markdown as plain text everywhere the item appears (inline math becomes
77
+ * `$…$`, math blocks `$$…$$`, code blocks are fenced). The code block header
78
+ * button and VoiceOver action always copy the raw code.
79
+ * @default { enabled: true, label: "Copy", format: "rich" }
71
80
  */
72
- copy?: { label?: string };
81
+ copy?: { enabled?: boolean; label?: string; format?: 'rich' | 'markdown' };
73
82
  /**
74
- * The built-in "Copy as Markdown" action for text selections.
83
+ * The built-in "Copy as Markdown" action, in the text selection menu and in
84
+ * the table / math / code block menus.
75
85
  * @default { enabled: true, label: "Copy as Markdown" }
76
86
  */
77
87
  copyAsMarkdown?: { enabled?: boolean; label?: string };
@@ -86,6 +96,23 @@ export interface SelectionMenuConfig {
86
96
  label?: string;
87
97
  pluralLabels?: SelectionMenuPluralLabels;
88
98
  };
99
+ /**
100
+ * Which system items the text selection menu keeps.
101
+ * - `'default'`: keep everything the OS adds (Select All, Look Up, Share,
102
+ * Translate, app text actions…), with Copy replaced by the built-in one.
103
+ * - `'none'`: drop every system item; the menu only holds the built-in items
104
+ * above and `contextMenuItems`.
105
+ * @default 'default'
106
+ * @platform ios, android
107
+ */
108
+ systemItems?: 'default' | 'none';
109
+ /**
110
+ * The copy button in the code block header. `false` hides the button; the
111
+ * header and language label stay.
112
+ * @default { enabled: true }
113
+ * @platform ios, android, macos
114
+ */
115
+ codeBlockCopyButton?: { enabled?: boolean };
89
116
  }
90
117
 
91
118
  export interface StreamingConfig {
@@ -98,6 +125,18 @@ export interface StreamingConfig {
98
125
  * @platform ios, android
99
126
  */
100
127
  tableMode?: 'hidden' | 'progressive';
128
+ /**
129
+ * Controls how a fenced code block whose closing fence has not arrived yet
130
+ * is handled during streaming.
131
+ * - `'hidden'`: hide the entire code block until its closing fence arrives.
132
+ * - `'progressive'` (default): show the code as it streams in with its header
133
+ * visible but non-interactive (copying is disabled); syntax highlighting is
134
+ * deferred until the closing fence arrives, so it appears once atomically.
135
+ * Only effective when `streamingAnimation` is `true`.
136
+ * @default 'progressive'
137
+ * @platform ios, android
138
+ */
139
+ codeBlockMode?: 'hidden' | 'progressive';
101
140
  }
102
141
 
103
142
  export interface EnrichedMarkdownTextProps extends Omit<ViewProps, 'style'> {
@@ -149,6 +188,31 @@ export interface EnrichedMarkdownTextProps extends Omit<ViewProps, 'style'> {
149
188
  * @platform ios, android, web
150
189
  */
151
190
  onTaskListItemPress?: (event: TaskListItemPressEvent) => void;
191
+ /**
192
+ * Controls whether tapping a task list checkbox toggles its checked state.
193
+ *
194
+ * When `true` (default), tapping the checkbox toggles it and fires
195
+ * `onTaskListItemPress`. When `false`, the checkbox renders its markdown
196
+ * state read-only: the tap is fully inert — no visual toggle and no
197
+ * `onTaskListItemPress` emission. Text selection and links in the same row
198
+ * are unaffected.
199
+ *
200
+ * @default true
201
+ * @platform ios, android, web
202
+ */
203
+ enableTaskListItemToggle?: boolean;
204
+ /**
205
+ * Callback fired when code is copied from a fenced code block, via the header
206
+ * copy button, the long-press context-menu "Copy" action, or the VoiceOver
207
+ * copy action. Receives the copied code and its language. Does not fire for
208
+ * "Copy as Markdown", nor for the context-menu "Copy" when
209
+ * `selectionMenuConfig.copy.format` is `'markdown'`.
210
+ *
211
+ * Only fires when `flavor="github"` (the copy button is part of the GitHub
212
+ * flavor's container-based code block renderer).
213
+ * @platform ios, android, macos
214
+ */
215
+ onCopyPress?: (event: CopyPressEvent) => void;
152
216
  /**
153
217
  * Controls whether the system link preview is shown on long press (iOS only).
154
218
  *
@@ -254,6 +318,34 @@ export interface EnrichedMarkdownTextProps extends Omit<ViewProps, 'style'> {
254
318
  * @platform ios, android
255
319
  */
256
320
  contextMenuItems?: ContextMenuItem[];
321
+ /**
322
+ * HTTP headers to attach to remote image requests, e.g. a `Referer`
323
+ * required by CDN hotlink protection or an `Authorization` token.
324
+ *
325
+ * Headers participate in image cache identity, so the same URL requested
326
+ * with different headers is fetched and cached separately.
327
+ *
328
+ * Not supported on web — browsers don't allow custom headers on `<img>`
329
+ * requests.
330
+ * @platform ios, android
331
+ */
332
+ imageRequestHeaders?: Record<string, string>;
333
+ /**
334
+ * Hides the text selection context menu. Text stays selectable (and stays
335
+ * reachable by TalkBack / VoiceOver) — only the menu is suppressed. Use
336
+ * `selectable={false}` instead if you want to disable selection itself.
337
+ *
338
+ * This hides the whole menu, including the custom items from
339
+ * `contextMenuItems` and the built-in items from `selectionMenuConfig`,
340
+ * since they all share one menu. It also covers the copy menus on table,
341
+ * math and code blocks.
342
+ *
343
+ * It does not suppress the system "Save to Camera Roll / Copy" sheet that
344
+ * UIKit shows when long-pressing an image.
345
+ * @default false
346
+ * @platform ios, android, macos
347
+ */
348
+ contextMenuHidden?: boolean;
257
349
  /**
258
350
  * Controls the built-in items added to the native text selection menu and
259
351
  * lets you localize their labels. Custom app-provided actions are controlled
@@ -58,6 +58,25 @@ export interface EnrichedMarkdownTextProps extends Omit<
58
58
  * @platform ios, android, web
59
59
  */
60
60
  onTaskListItemPress?: (event: TaskListItemPressEvent) => void;
61
+ /**
62
+ * Controls whether tapping a task list checkbox toggles its checked state.
63
+ *
64
+ * When `true` (default), tapping the checkbox toggles it and fires
65
+ * `onTaskListItemPress`. When `false`, the checkbox renders its markdown
66
+ * state read-only: the tap is fully inert — no visual toggle and no
67
+ * `onTaskListItemPress` emission. Text selection and links in the same row
68
+ * are unaffected.
69
+ *
70
+ * On web the checkbox keeps its normal appearance and is marked
71
+ * `readOnly` / `aria-disabled` rather than `disabled`, so it stays visually
72
+ * consistent with iOS and Android. It is also made pointer-inert
73
+ * (`pointer-events: none`) so the browser cannot paint hover or active
74
+ * states on a checkbox that cannot be toggled.
75
+ *
76
+ * @default true
77
+ * @platform ios, android, web
78
+ */
79
+ enableTaskListItemToggle?: boolean;
61
80
  /**
62
81
  * Controls text selection.
63
82
  * - iOS: Controls text selection and link previews on long press.
@@ -12,6 +12,11 @@ export interface TaskListItemPressEvent {
12
12
  text: string;
13
13
  }
14
14
 
15
+ export interface CopyPressEvent {
16
+ code: string;
17
+ language: string;
18
+ }
19
+
15
20
  /**
16
21
  * Native-level context menu item config sent to the native component.
17
22
  * Does not include the `onPress` callback — callbacks are managed on the JS side.
@@ -30,3 +35,19 @@ export interface OnContextMenuItemPressEvent {
30
35
  selectionStart: number;
31
36
  selectionEnd: number;
32
37
  }
38
+
39
+ /**
40
+ * Event payload fired by the native component when the user pastes while
41
+ * `interceptPaste` is on. Native does not touch the buffer — it only reports
42
+ * what the clipboard held. The handler must call `resolvePaste` exactly once,
43
+ * or the paste is dropped.
44
+ */
45
+ export interface OnPasteEvent {
46
+ /** Plain text from the clipboard, verbatim, before the text view sees it. */
47
+ text: string;
48
+ /**
49
+ * Markdown flavor, set only when the copy source was an input of this
50
+ * component. iOS-only; Android always reports `''`.
51
+ */
52
+ markdown: string;
53
+ }
@@ -0,0 +1,35 @@
1
+ /**
2
+ * Bridges EnrichedMarkdownTextInput into React Native's TextInputState focus
3
+ * registry so it participates in RN's keyboard-dismiss behavior (issue #577).
4
+ *
5
+ * Registering a non-TextInput host component is safe: TextInputState's
6
+ * blurTextInput dispatches the built-in TextInput's "blur" command at the
7
+ * registered instance, and Fabric command dispatch is name-based — it works
8
+ * as long as the component ships a command with that name, which ours does.
9
+ *
10
+ * A deep import is required because the public TextInput.State API lacks the
11
+ * registerInput/focusInput/blurInput bookkeeping functions.
12
+ */
13
+ import type { HostInstance } from 'react-native';
14
+
15
+ interface TextInputStateModule {
16
+ registerInput(input: HostInstance): void;
17
+ unregisterInput(input: HostInstance): void;
18
+ focusInput(input: HostInstance | null): void;
19
+ blurInput(input: HostInstance | null): void;
20
+ blurTextInput(input: HostInstance | null): void;
21
+ currentlyFocusedInput(): HostInstance | null;
22
+ }
23
+
24
+ /**
25
+ * The internal module's export shape has changed across RN versions: newer
26
+ * versions use `export default` (surfacing as `.default` after Metro's CJS
27
+ * transform) while older ones assigned `module.exports` directly. A raw
28
+ * require bypasses Babel's import interop, so both shapes are handled here.
29
+ */
30
+ const TextInputStateModuleImpl =
31
+ // eslint-disable-next-line @react-native/no-deep-imports
32
+ require('react-native/Libraries/Components/TextInput/TextInputState');
33
+
34
+ export const TextInputState = (TextInputStateModuleImpl.default ??
35
+ TextInputStateModuleImpl) as TextInputStateModule;
@@ -21,6 +21,7 @@ export const EnrichedMarkdownText = ({
21
21
  onLinkPress,
22
22
  onLinkLongPress,
23
23
  onTaskListItemPress,
24
+ enableTaskListItemToggle = true,
24
25
  allowTrailingMargin = false,
25
26
  containerStyle,
26
27
  selectable = true,
@@ -43,6 +44,7 @@ export const EnrichedMarkdownText = ({
43
44
  superscript = false,
44
45
  subscript = false,
45
46
  highlight = false,
47
+ hardSoftBreaks = false,
46
48
  } = md4cFlags;
47
49
 
48
50
  useEffect(() => {
@@ -57,6 +59,7 @@ export const EnrichedMarkdownText = ({
57
59
  superscript,
58
60
  subscript,
59
61
  highlight,
62
+ hardSoftBreaks,
60
63
  }),
61
64
  katexPromise,
62
65
  ])
@@ -85,14 +88,25 @@ export const EnrichedMarkdownText = ({
85
88
  return () => {
86
89
  cancelled = true;
87
90
  };
88
- }, [markdown, underline, latexMath, superscript, subscript, highlight]);
91
+ }, [
92
+ markdown,
93
+ underline,
94
+ latexMath,
95
+ superscript,
96
+ subscript,
97
+ highlight,
98
+ hardSoftBreaks,
99
+ ]);
89
100
 
90
101
  const callbacks = useMemo<RendererCallbacks>(
91
102
  () => ({ onLinkPress, onLinkLongPress, onTaskListItemPress }),
92
103
  [onLinkPress, onLinkLongPress, onTaskListItemPress]
93
104
  );
94
105
 
95
- const capabilities = useMemo<RenderCapabilities>(() => ({ katex }), [katex]);
106
+ const capabilities = useMemo<RenderCapabilities>(
107
+ () => ({ katex, enableTaskListItemToggle }),
108
+ [katex, enableTaskListItemToggle]
109
+ );
96
110
 
97
111
  const lastChildStyle = useMemo(
98
112
  () =>
@@ -7,7 +7,8 @@ type ParseFn = (
7
7
  latexMath: number,
8
8
  superscript: number,
9
9
  subscript: number,
10
- highlight: number
10
+ highlight: number,
11
+ hardSoftBreaks: number
11
12
  ) => string;
12
13
 
13
14
  // Caching the Promise (not the resolved value) means concurrent callers share
@@ -28,6 +29,7 @@ function initializeParser(): Promise<ParseFn> {
28
29
  'number',
29
30
  'number',
30
31
  'number',
32
+ 'number',
31
33
  ])
32
34
  )
33
35
  .catch((error) => {
@@ -55,6 +57,7 @@ export async function parseMarkdown(
55
57
  superscript = false,
56
58
  subscript = false,
57
59
  highlight = false,
60
+ hardSoftBreaks = false,
58
61
  }: Md4cFlags = {}
59
62
  ): Promise<ASTNode> {
60
63
  const parse = await initializeParser();
@@ -66,7 +69,8 @@ export async function parseMarkdown(
66
69
  latexMath ? 1 : 0,
67
70
  superscript ? 1 : 0,
68
71
  subscript ? 1 : 0,
69
- highlight ? 1 : 0
72
+ highlight ? 1 : 0,
73
+ hardSoftBreaks ? 1 : 0
70
74
  )
71
75
  );
72
76
 
@@ -12,6 +12,10 @@ function LineBreakRenderer(_props: RendererProps) {
12
12
  return <br />;
13
13
  }
14
14
 
15
+ function SoftBreakRenderer(_props: RendererProps) {
16
+ return <> </>;
17
+ }
18
+
15
19
  function StrongRenderer({ node, styles, renderChildren }: RendererProps) {
16
20
  return <strong style={styles.strong}>{renderChildren(node)}</strong>;
17
21
  }
@@ -108,6 +112,7 @@ function LatexMathInlineRenderer({
108
112
  export const inlineRenderers: RendererMap = {
109
113
  Text: TextRenderer,
110
114
  LineBreak: LineBreakRenderer,
115
+ SoftBreak: SoftBreakRenderer,
111
116
  Strong: StrongRenderer,
112
117
  Emphasis: EmphasisRenderer,
113
118
  Strikethrough: StrikethroughRenderer,
@@ -44,7 +44,9 @@ function ListItemRenderer({
44
44
  node,
45
45
  style,
46
46
  styles,
47
+ index,
47
48
  callbacks,
49
+ capabilities,
48
50
  renderChildren,
49
51
  }: RendererProps) {
50
52
  const isTask = node.attributes?.isTask === 'true';
@@ -57,6 +59,8 @@ function ListItemRenderer({
57
59
  }, [initialChecked]);
58
60
 
59
61
  const handleChange = () => {
62
+ if (!capabilities.enableTaskListItemToggle) return;
63
+
60
64
  const taskIndex = node.attributes?.taskIndex;
61
65
  if (taskIndex === undefined) return;
62
66
 
@@ -85,14 +89,22 @@ function ListItemRenderer({
85
89
  : null;
86
90
 
87
91
  return (
88
- <li style={listItemStyle(isTask)}>
92
+ <li style={listItemStyle(style, isTask, (index ?? 0) === 0)}>
89
93
  <span style={checkedStyle}>
90
94
  {isTask && (
91
95
  <input
92
96
  type="checkbox"
93
97
  checked={isChecked}
94
98
  onChange={handleChange}
95
- style={styles.taskCheckbox}
99
+ readOnly={!capabilities.enableTaskListItemToggle}
100
+ aria-disabled={
101
+ capabilities.enableTaskListItemToggle ? undefined : true
102
+ }
103
+ style={
104
+ capabilities.enableTaskListItemToggle
105
+ ? styles.taskCheckbox
106
+ : styles.taskCheckboxDisabled
107
+ }
96
108
  aria-label={`Task: ${taskText}`}
97
109
  />
98
110
  )}
@@ -35,6 +35,7 @@ export interface RenderNodeProps {
35
35
  callbacks: RendererCallbacks;
36
36
  capabilities: RenderCapabilities;
37
37
  parentType?: NodeType;
38
+ index?: number;
38
39
  }
39
40
 
40
41
  export function RenderNode({
@@ -44,20 +45,22 @@ export function RenderNode({
44
45
  callbacks,
45
46
  capabilities,
46
47
  parentType,
48
+ index,
47
49
  }: RenderNodeProps): ReactNode {
48
50
  const Renderer = RENDERERS[node.type];
49
51
  if (!Renderer) return null;
50
52
 
51
53
  const renderChildren = (childNode: ASTNode): ReactNode =>
52
- childNode.children?.map((child, index) => (
54
+ childNode.children?.map((child, childIndex) => (
53
55
  <RenderNode
54
- key={nodeKey(child, index)}
56
+ key={nodeKey(child, childIndex)}
55
57
  node={child}
56
58
  style={style}
57
59
  styles={styles}
58
60
  callbacks={callbacks}
59
61
  capabilities={capabilities}
60
62
  parentType={childNode.type}
63
+ index={childIndex}
61
64
  />
62
65
  )) ?? null;
63
66
 
@@ -67,6 +70,7 @@ export function RenderNode({
67
70
  style={style}
68
71
  styles={styles}
69
72
  parentType={parentType}
73
+ index={index}
70
74
  callbacks={callbacks}
71
75
  capabilities={capabilities}
72
76
  renderChildren={renderChildren}
package/src/web/styles.ts CHANGED
@@ -126,7 +126,11 @@ function blockquoteStyle(style: MarkdownStyleInternal): CSSProperties {
126
126
  marginInlineStart: 0, // reset UA default (40px in LTR, auto in RTL)
127
127
  marginInlineEnd: 0,
128
128
  paddingInlineStart: blockquote.gapWidth,
129
+ paddingInlineEnd: blockquote.padding,
130
+ paddingTop: blockquote.padding,
131
+ paddingBottom: blockquote.padding,
129
132
  borderInlineStart: `${blockquote.borderWidth}px solid ${blockquote.borderColor}`,
133
+ borderRadius: blockquote.borderRadius,
130
134
  backgroundColor: blockquote.backgroundColor,
131
135
  };
132
136
  }
@@ -180,16 +184,55 @@ function thematicBreakStyle(style: MarkdownStyleInternal): CSSProperties {
180
184
  };
181
185
  }
182
186
 
187
+ const RESIZE_MODE_TO_OBJECT_FIT: Record<
188
+ Exclude<MarkdownStyleInternal['image']['resizeMode'], ''>,
189
+ NonNullable<CSSProperties['objectFit']>
190
+ > = {
191
+ contain: 'contain',
192
+ cover: 'cover',
193
+ stretch: 'fill',
194
+ center: 'scale-down',
195
+ none: 'none',
196
+ };
197
+
183
198
  function imageStyle(style: MarkdownStyleInternal): CSSProperties {
184
199
  const image = style.image;
185
- return {
186
- height: image.height,
200
+ const base: CSSProperties = {
187
201
  borderRadius: image.borderRadius,
188
202
  marginTop: image.marginTop,
189
203
  marginBottom: image.marginBottom,
190
204
  maxWidth: '100%',
191
205
  display: 'block',
192
206
  };
207
+
208
+ // Sizing precedence: aspectRatio > maxHeight > height. resizeMode '' means
209
+ // legacy sizing — emit today's exact CSS for backward compatibility.
210
+ if (image.resizeMode === '') {
211
+ return { ...base, height: image.height };
212
+ }
213
+
214
+ const objectFit = RESIZE_MODE_TO_OBJECT_FIT[image.resizeMode] ?? 'cover';
215
+
216
+ if (image.aspectRatio > 0) {
217
+ return {
218
+ ...base,
219
+ width: '100%',
220
+ aspectRatio: image.aspectRatio,
221
+ objectFit,
222
+ };
223
+ }
224
+
225
+ if (image.maxHeight > 0) {
226
+ return {
227
+ ...base,
228
+ width: '100%',
229
+ height: 'auto',
230
+ maxHeight: image.maxHeight,
231
+ objectFit,
232
+ };
233
+ }
234
+
235
+ return { ...base, width: '100%', height: image.height, objectFit };
193
236
  }
194
237
 
195
238
  function inlineImageStyle(style: MarkdownStyleInternal): CSSProperties {
@@ -368,8 +411,17 @@ function tableStyle(style: MarkdownStyleInternal): CSSProperties {
368
411
  };
369
412
  }
370
413
 
371
- export function listItemStyle(isTask: boolean): CSSProperties | undefined {
372
- return isTask ? { listStyle: 'none' } : undefined;
414
+ export function listItemStyle(
415
+ style: MarkdownStyleInternal,
416
+ isTask: boolean,
417
+ isFirstChild: boolean
418
+ ): CSSProperties | undefined {
419
+ const { itemSpacing } = style.list;
420
+ const marginTop = !isFirstChild && itemSpacing > 0 ? itemSpacing : undefined;
421
+ if (isTask) {
422
+ return { listStyle: 'none', marginTop };
423
+ }
424
+ return marginTop !== undefined ? { marginTop } : undefined;
373
425
  }
374
426
 
375
427
  export function checkedTaskTextStyle(
@@ -384,6 +436,21 @@ export function checkedTaskTextStyle(
384
436
  };
385
437
  }
386
438
 
439
+ /**
440
+ * Checkbox style used when `enableTaskListItemToggle` is `false`. Pointer-inert
441
+ * so the browser paints no hover/active state on a checkbox that cannot be
442
+ * toggled; appearance is otherwise identical to the enabled checkbox.
443
+ */
444
+ function taskCheckboxDisabledStyle(
445
+ style: MarkdownStyleInternal
446
+ ): CSSProperties {
447
+ return {
448
+ ...taskCheckboxStyle(style),
449
+ pointerEvents: 'none',
450
+ cursor: 'default',
451
+ };
452
+ }
453
+
387
454
  function taskCheckboxStyle(style: MarkdownStyleInternal): CSSProperties {
388
455
  const taskList = style.taskList;
389
456
  return {
@@ -411,11 +478,20 @@ export function tableBodyRowStyle(
411
478
 
412
479
  function tableWrapperStyle(style: MarkdownStyleInternal): CSSProperties {
413
480
  const table = style.table;
481
+ const alignment: CSSProperties = table.align
482
+ ? {
483
+ width: 'fit-content',
484
+ maxWidth: '100%',
485
+ marginLeft: table.align === 'left' ? 0 : 'auto',
486
+ marginRight: table.align === 'right' ? 0 : 'auto',
487
+ }
488
+ : {};
414
489
  return {
415
490
  overflowX: 'auto',
416
491
  overflowY: 'hidden',
417
492
  marginTop: table.marginTop,
418
493
  marginBottom: table.marginBottom,
494
+ ...alignment,
419
495
  // borderRadius must live on the wrapper, not the <table> — border-collapse:
420
496
  // collapse causes browsers to ignore border-radius on the table element itself.
421
497
  borderRadius: table.borderRadius,
@@ -491,6 +567,7 @@ export interface Styles {
491
567
  tableHeaderCell: Record<ColumnAlign, CSSProperties>;
492
568
  tableCell: Record<ColumnAlign, CSSProperties>;
493
569
  taskCheckbox: CSSProperties;
570
+ taskCheckboxDisabled: CSSProperties;
494
571
  }
495
572
 
496
573
  type ColumnAlign = 'left' | 'center' | 'right' | 'default';
@@ -513,7 +590,13 @@ export function buildStyles(style: MarkdownStyleInternal): Styles {
513
590
  h6: headingStyle(style, '6'),
514
591
  blockquote: blockquoteStyle(style),
515
592
  list: listStyle(style),
516
- listNested: { ...listStyle(style), marginBottom: 0 },
593
+ listNested: {
594
+ ...listStyle(style),
595
+ // A nested list sits directly under its parent item's text; itemSpacing
596
+ // (not the list's outer margins) controls that gap, like on native.
597
+ marginTop: Math.max(0, style.list.itemSpacing),
598
+ marginBottom: 0,
599
+ },
517
600
  listTask: listStyle(style, true),
518
601
  codeBlock,
519
602
  codeBlockFont: { fontFamily: codeBlock.fontFamily },
@@ -546,6 +629,7 @@ export function buildStyles(style: MarkdownStyleInternal): Styles {
546
629
  default: tableCellStyle(style, 'default'),
547
630
  },
548
631
  taskCheckbox: taskCheckboxStyle(style),
632
+ taskCheckboxDisabled: taskCheckboxDisabledStyle(style),
549
633
  };
550
634
 
551
635
  stylesStore.set(style, result);
package/src/web/types.ts CHANGED
@@ -15,6 +15,7 @@ export type NodeType =
15
15
  | 'Link'
16
16
  | 'Heading'
17
17
  | 'LineBreak'
18
+ | 'SoftBreak'
18
19
  | 'Strong'
19
20
  | 'Emphasis'
20
21
  | 'Strikethrough'
@@ -63,7 +64,7 @@ export interface ASTNode {
63
64
  content?: string;
64
65
  /** Present on nodes that carry structural metadata (Heading, Link, etc.). */
65
66
  attributes?: NodeAttributes;
66
- /** Child nodes; absent on leaf nodes (Text, LineBreak, ThematicBreak). */
67
+ /** Child nodes; absent on leaf nodes (Text, LineBreak, SoftBreak, ThematicBreak). */
67
68
  children?: ASTNode[];
68
69
  }
69
70
 
@@ -75,6 +76,8 @@ export interface RendererCallbacks {
75
76
 
76
77
  export interface RenderCapabilities {
77
78
  katex: KaTeXInstance | null;
79
+ /** When false, task list checkboxes render read-only and ignore clicks. */
80
+ enableTaskListItemToggle: boolean;
78
81
  }
79
82
 
80
83
  export interface RendererProps {
@@ -82,6 +85,8 @@ export interface RendererProps {
82
85
  style: MarkdownStyleInternal;
83
86
  styles: Styles;
84
87
  parentType?: NodeType;
88
+ /** Position among the parent node's children. */
89
+ index?: number;
85
90
  callbacks: RendererCallbacks;
86
91
  capabilities: RenderCapabilities;
87
92
  renderChildren: (node: ASTNode) => ReactNode;
package/src/web/utils.ts CHANGED
@@ -2,6 +2,7 @@ import type { ASTNode } from './types';
2
2
 
3
3
  /** Recursively collects plain text content from an AST node's subtree. */
4
4
  export function extractNodeText(node: ASTNode): string {
5
+ if (node.type === 'SoftBreak' || node.type === 'LineBreak') return ' ';
5
6
  if (node.content !== undefined) return node.content;
6
7
  return node.children?.map(extractNodeText).join('') ?? '';
7
8
  }
Binary file