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
@@ -0,0 +1,228 @@
1
+ #import "ENRMEditPipeline.h"
2
+ #import "ENRMBlockHandler.h"
3
+ #import "ENRMBlockStore.h"
4
+ #import "ENRMDetectorPipeline.h"
5
+ #import "ENRMFormattingRange.h"
6
+ #import "ENRMFormattingStore.h"
7
+ #import "ENRMInputFormatter.h"
8
+ #import "ENRMUIKit.h"
9
+
10
+ @implementation ENRMEditContext
11
+
12
+ - (instancetype)initWithEditLocation:(NSUInteger)editLocation
13
+ deletedLength:(NSUInteger)deletedLength
14
+ insertedLength:(NSUInteger)insertedLength
15
+ preEditReplacedNewline:(BOOL)preEditReplacedNewline
16
+ preEditBlockType:(ENRMInputBlockType)preEditBlockType
17
+ preEditBlockLevel:(NSInteger)preEditBlockLevel
18
+ preEditParagraphWasEmpty:(BOOL)preEditParagraphWasEmpty
19
+ pendingStyles:(NSSet<NSNumber *> *)pendingStyles
20
+ pendingStyleRemovals:(NSSet<NSNumber *> *)pendingStyleRemovals
21
+ {
22
+ if (self = [super init]) {
23
+ _editLocation = editLocation;
24
+ _deletedLength = deletedLength;
25
+ _insertedLength = insertedLength;
26
+ _preEditReplacedNewline = preEditReplacedNewline;
27
+ _preEditBlockType = preEditBlockType;
28
+ _preEditBlockLevel = preEditBlockLevel;
29
+ _preEditParagraphWasEmpty = preEditParagraphWasEmpty;
30
+ _pendingStyles = [pendingStyles copy];
31
+ _pendingStyleRemovals = [pendingStyleRemovals copy];
32
+ }
33
+ return self;
34
+ }
35
+
36
+ @end
37
+
38
+ @implementation ENRMEditPipeline {
39
+ ENRMFormattingStore *_formattingStore;
40
+ ENRMBlockStore *_blockStore;
41
+ ENRMInputFormatter *_formatter;
42
+ ENRMDetectorPipeline *_detectorPipeline;
43
+ __weak id<ENRMEditPipelineHost> _host;
44
+ }
45
+
46
+ - (instancetype)initWithFormattingStore:(ENRMFormattingStore *)formattingStore
47
+ blockStore:(ENRMBlockStore *)blockStore
48
+ formatter:(ENRMInputFormatter *)formatter
49
+ detectorPipeline:(ENRMDetectorPipeline *)detectorPipeline
50
+ host:(id<ENRMEditPipelineHost>)host
51
+ {
52
+ if (self = [super init]) {
53
+ _formattingStore = formattingStore;
54
+ _blockStore = blockStore;
55
+ _formatter = formatter;
56
+ _detectorPipeline = detectorPipeline;
57
+ _host = host;
58
+ }
59
+ return self;
60
+ }
61
+
62
+ #pragma mark - Public API
63
+
64
+ - (BOOL)processTextChangeWithContext:(ENRMEditContext *)context
65
+ {
66
+ NSUInteger editLocation = context.editLocation;
67
+ NSUInteger insertedLength = context.insertedLength;
68
+
69
+ [self adjustStoresForEditAtLocation:editLocation deletedLength:context.deletedLength insertedLength:insertedLength];
70
+
71
+ NSString *plainText = [_host plainText];
72
+
73
+ if (insertedLength > 0) {
74
+ BOOL insertedHasGlyphContent = [self insertedHasGlyphContentAtLocation:editLocation
75
+ length:insertedLength
76
+ text:plainText];
77
+ [self applyPendingStylesWithContext:context plainText:plainText hasGlyphContent:insertedHasGlyphContent];
78
+
79
+ if (!insertedHasGlyphContent && insertedLength == 1) {
80
+ [self reconcileBlockContinuationAfterNewlineAt:editLocation
81
+ previousItemWasEmpty:context.preEditParagraphWasEmpty
82
+ preEditBlockType:context.preEditBlockType
83
+ preEditBlockLevel:context.preEditBlockLevel];
84
+ // Continuation re-seeds fresh block ranges whose ordinal defaults to 1;
85
+ // normalize again so the list-metadata pass renumbers the adjacent run.
86
+ [_blockStore normalizeToLineBoundsInText:[_host plainText]];
87
+ }
88
+ }
89
+
90
+ // Determine whether the edit touched a newline (for full-vs-scoped formatting).
91
+ BOOL touchedNewline = context.preEditReplacedNewline;
92
+ if (!touchedNewline && insertedLength > 0) {
93
+ NSString *postEditText = [_host plainText];
94
+ NSUInteger insertedEnd = MIN(editLocation + insertedLength, postEditText.length);
95
+ if (editLocation < insertedEnd) {
96
+ NSRange insertedRun = NSMakeRange(editLocation, insertedEnd - editLocation);
97
+ touchedNewline = [postEditText rangeOfCharacterFromSet:[NSCharacterSet newlineCharacterSet]
98
+ options:0
99
+ range:insertedRun]
100
+ .location != NSNotFound;
101
+ }
102
+ }
103
+
104
+ return touchedNewline;
105
+ }
106
+
107
+ - (NSString *)adjustStoresForEditAtLocation:(NSUInteger)editLocation
108
+ deletedLength:(NSUInteger)deletedLength
109
+ insertedLength:(NSUInteger)insertedLength
110
+ {
111
+ [_formattingStore adjustForEditAtLocation:editLocation deletedLength:deletedLength insertedLength:insertedLength];
112
+ [_blockStore adjustForEditAtLocation:editLocation deletedLength:deletedLength insertedLength:insertedLength];
113
+ [self pruneOrphanedBlockAnchors];
114
+ NSString *plainText = [_host plainText];
115
+ [_blockStore normalizeToLineBoundsInText:plainText];
116
+ return plainText;
117
+ }
118
+
119
+ - (void)pruneOrphanedBlockAnchors
120
+ {
121
+ NSString *text = [_host textStorage].string;
122
+ for (ENRMBlockRange *block in _blockStore.allRanges) {
123
+ if (!ENRMBlockTypePersistsWhenEmpty(block.type)) {
124
+ continue;
125
+ }
126
+ NSUInteger anchor = MIN(block.range.location, text.length);
127
+ BOOL atLineStart = [text paragraphRangeForRange:NSMakeRange(anchor, 0)].location == anchor;
128
+ if (!atLineStart) {
129
+ [_blockStore removeBlockInParagraphRange:NSMakeRange(anchor, 0) inText:text];
130
+ }
131
+ }
132
+ }
133
+
134
+ - (void)detectLinksAtLocation:(NSUInteger)editLocation insertedLength:(NSUInteger)insertedLength
135
+ {
136
+ NSString *currentText = [_host plainText];
137
+ NSUInteger clampedEditLocation = MIN(editLocation, currentText.length);
138
+ NSUInteger clampedInsertedLength = MIN(insertedLength, currentText.length - clampedEditLocation);
139
+ [_detectorPipeline processTextChange:currentText
140
+ modificationRange:NSMakeRange(clampedEditLocation, clampedInsertedLength)];
141
+ }
142
+
143
+ #pragma mark - Pending styles (private)
144
+
145
+ - (void)applyPendingStylesWithContext:(ENRMEditContext *)context
146
+ plainText:(NSString *)plainText
147
+ hasGlyphContent:(BOOL)insertedHasGlyphContent
148
+ {
149
+ NSRange insertedRange = NSMakeRange(context.editLocation, context.insertedLength);
150
+
151
+ if (insertedHasGlyphContent) {
152
+ for (NSNumber *styleNum in context.pendingStyles) {
153
+ ENRMFormattingRange *newRange = [ENRMFormattingRange rangeWithType:(ENRMInputStyleType)styleNum.integerValue
154
+ range:insertedRange];
155
+ [_formattingStore addRange:newRange];
156
+ }
157
+ }
158
+
159
+ // adjustForEditAtLocation may have expanded an existing range to cover
160
+ // the insertion — carve out the inserted portion for removed styles.
161
+ for (NSNumber *styleNum in context.pendingStyleRemovals) {
162
+ [_formattingStore removeType:(ENRMInputStyleType)styleNum.integerValue inRange:insertedRange];
163
+ }
164
+ }
165
+
166
+ - (BOOL)insertedHasGlyphContentAtLocation:(NSUInteger)location length:(NSUInteger)length text:(NSString *)text
167
+ {
168
+ NSUInteger insertedEnd = location + length;
169
+ if (insertedEnd > text.length)
170
+ return NO;
171
+ NSCharacterSet *newlines = [NSCharacterSet newlineCharacterSet];
172
+ for (NSUInteger i = location; i < insertedEnd; i++) {
173
+ if (![newlines characterIsMember:[text characterAtIndex:i]]) {
174
+ return YES;
175
+ }
176
+ }
177
+ return NO;
178
+ }
179
+
180
+ #pragma mark - Block continuation (private)
181
+
182
+ /// Reconciles blocks after Return: a non-empty item continues as a new item at
183
+ /// the same depth, an empty item exits the list (both lines revert to plain
184
+ /// paragraphs). Whether a type continues is the handler's continuesOnNewline.
185
+ - (void)reconcileBlockContinuationAfterNewlineAt:(NSUInteger)newlineLocation
186
+ previousItemWasEmpty:(BOOL)previousWasEmpty
187
+ preEditBlockType:(ENRMInputBlockType)blockType
188
+ preEditBlockLevel:(NSInteger)blockLevel
189
+ {
190
+ id<ENRMBlockHandler> handler = [_formatter handlerForBlockType:blockType];
191
+ if (!handler || ![handler respondsToSelector:@selector(continuesOnNewline)] || !handler.continuesOnNewline) {
192
+ return;
193
+ }
194
+
195
+ NSString *text = [_host plainText];
196
+ NSUInteger newLineLocation = newlineLocation + 1;
197
+ if (newLineLocation > text.length) {
198
+ return;
199
+ }
200
+ NSRange originalParagraph = [text paragraphRangeForRange:NSMakeRange(newlineLocation, 0)];
201
+ NSRange newParagraph = [text paragraphRangeForRange:NSMakeRange(newLineLocation, 0)];
202
+
203
+ if (previousWasEmpty) {
204
+ // Exit: drop the block from both lines and strip their list paragraph style.
205
+ // Empty lines carry no stamped block-marker attribute for applyFormatting to
206
+ // key off, so the manual strip is the only thing that clears the leftover indent.
207
+ [_blockStore removeBlockInParagraphRange:originalParagraph inText:text];
208
+ [_blockStore removeBlockInParagraphRange:newParagraph inText:text];
209
+
210
+ NSTextStorage *storage = [_host textStorage];
211
+ [storage beginEditing];
212
+ NSRange clamped = NSIntersectionRange(originalParagraph, NSMakeRange(0, storage.length));
213
+ if (clamped.length > 0) {
214
+ [storage removeAttribute:NSParagraphStyleAttributeName range:clamped];
215
+ }
216
+ clamped = NSIntersectionRange(newParagraph, NSMakeRange(0, storage.length));
217
+ if (clamped.length > 0) {
218
+ [storage removeAttribute:NSParagraphStyleAttributeName range:clamped];
219
+ }
220
+ [storage endEditing];
221
+ return;
222
+ }
223
+
224
+ [_blockStore setBlockType:blockType level:blockLevel forParagraphRange:originalParagraph inText:text];
225
+ [_blockStore setBlockType:blockType level:blockLevel forParagraphRange:newParagraph inText:text];
226
+ }
227
+
228
+ @end
@@ -0,0 +1,36 @@
1
+ #import "ENRMUIKit.h"
2
+ #import <Foundation/Foundation.h>
3
+
4
+ NS_ASSUME_NONNULL_BEGIN
5
+
6
+ typedef NS_ENUM(NSInteger, ENRMEditPhase) {
7
+ ENRMEditPhaseIdle,
8
+ ENRMEditPhaseProcessing,
9
+ ENRMEditPhaseFormatting,
10
+ ENRMEditPhaseImporting,
11
+ };
12
+
13
+ /// Tracks the current editing phase and exposes computed suppression queries.
14
+ /// Replaces the scattered boolean flags (`_isApplyingFormatting`, `_isTextChanging`,
15
+ /// `blockEmitting`, `_lastTextChangeTime`) that previously guarded re-entrant
16
+ /// code paths in the view.
17
+ @interface ENRMEditSession : NSObject
18
+
19
+ @property (nonatomic, readonly) ENRMEditPhase phase;
20
+
21
+ - (instancetype)initWithTextView:(ENRMPlatformTextView *)textView;
22
+
23
+ - (void)enterPhase:(ENRMEditPhase)newPhase;
24
+ - (void)exitPhase;
25
+
26
+ - (void)recordTextChange;
27
+
28
+ @property (nonatomic, readonly) BOOL isComposing;
29
+ @property (nonatomic, readonly) BOOL isPostEditGracePeriod;
30
+ @property (nonatomic, readonly) BOOL shouldSuppressFormatting;
31
+ @property (nonatomic, readonly) BOOL shouldSuppressEvents;
32
+ @property (nonatomic, readonly) BOOL shouldSuppressSelectionSideEffects;
33
+
34
+ @end
35
+
36
+ NS_ASSUME_NONNULL_END
@@ -0,0 +1,63 @@
1
+ #import "ENRMEditSession.h"
2
+
3
+ static const CFTimeInterval kPostEditGracePeriod = 0.1;
4
+
5
+ @implementation ENRMEditSession {
6
+ __weak ENRMPlatformTextView *_textView;
7
+ CFTimeInterval _lastTextChangeTime;
8
+ }
9
+
10
+ - (instancetype)initWithTextView:(ENRMPlatformTextView *)textView
11
+ {
12
+ if (self = [super init]) {
13
+ _textView = textView;
14
+ _phase = ENRMEditPhaseIdle;
15
+ _lastTextChangeTime = 0;
16
+ }
17
+ return self;
18
+ }
19
+
20
+ - (void)enterPhase:(ENRMEditPhase)newPhase
21
+ {
22
+ _phase = newPhase;
23
+ }
24
+
25
+ - (void)exitPhase
26
+ {
27
+ _phase = ENRMEditPhaseIdle;
28
+ }
29
+
30
+ - (void)recordTextChange
31
+ {
32
+ _lastTextChangeTime = CACurrentMediaTime();
33
+ }
34
+
35
+ - (BOOL)isComposing
36
+ {
37
+ ENRMPlatformTextView *tv = _textView;
38
+ if (!tv)
39
+ return NO;
40
+ return ENRMHasMarkedText(tv);
41
+ }
42
+
43
+ - (BOOL)isPostEditGracePeriod
44
+ {
45
+ return _lastTextChangeTime > 0 && (CACurrentMediaTime() - _lastTextChangeTime) < kPostEditGracePeriod;
46
+ }
47
+
48
+ - (BOOL)shouldSuppressFormatting
49
+ {
50
+ return _phase == ENRMEditPhaseFormatting || _phase == ENRMEditPhaseImporting;
51
+ }
52
+
53
+ - (BOOL)shouldSuppressEvents
54
+ {
55
+ return _phase == ENRMEditPhaseImporting;
56
+ }
57
+
58
+ - (BOOL)shouldSuppressSelectionSideEffects
59
+ {
60
+ return _phase != ENRMEditPhaseIdle;
61
+ }
62
+
63
+ @end
@@ -21,6 +21,23 @@ NS_ASSUME_NONNULL_BEGIN
21
21
  /// the whole link, a caret inside a link moves to its end (unchanged when no adjustment is needed).
22
22
  - (NSRange)selectionAdjustedForAtomicLinks:(NSRange)selection;
23
23
 
24
+ /// YES when the entire `range` is covered by adjacent/overlapping ranges of `type`.
25
+ - (BOOL)isStyleFullyActive:(ENRMInputStyleType)type inRange:(NSRange)range;
26
+
27
+ /// Toggles `type` on `range`. For a selection (length > 0), removes the style
28
+ /// when fully active, otherwise strips `conflictingStyles` and adds it.
29
+ /// For a caret (length == 0), reports the current state without mutating.
30
+ /// Returns YES when the style was active (removed / pending removal).
31
+ - (BOOL)toggleStyle:(ENRMInputStyleType)type
32
+ inRange:(NSRange)range
33
+ conflictingStyles:(NSSet<NSNumber *> *)conflictingStyles;
34
+
35
+ /// YES when toggling `type` ON at `position` should be refused because one of
36
+ /// the `blockingStyles` is active there. Toggling OFF is never blocked.
37
+ - (BOOL)isToggleBlocked:(ENRMInputStyleType)type
38
+ atPosition:(NSUInteger)position
39
+ blockingStyles:(NSSet<NSNumber *> *)blockingStyles;
40
+
24
41
  - (void)addRange:(ENRMFormattingRange *)range;
25
42
  - (void)removeType:(ENRMInputStyleType)type inRange:(NSRange)range;
26
43
  - (void)removeRange:(ENRMFormattingRange *)range;
@@ -1,46 +1,6 @@
1
1
  #import "ENRMFormattingStore.h"
2
-
3
- static NSUInteger sortedInsertionIndex(NSArray<ENRMFormattingRange *> *ranges, NSUInteger location)
4
- {
5
- NSUInteger index = 0;
6
- for (ENRMFormattingRange *existing in ranges) {
7
- if (existing.range.location > location)
8
- break;
9
- index++;
10
- }
11
- return index;
12
- }
13
-
14
- static void removeIndexesInReverse(NSMutableArray *array, NSMutableIndexSet *indexes)
15
- {
16
- [indexes enumerateIndexesWithOptions:NSEnumerationReverse
17
- usingBlock:^(NSUInteger idx, BOOL *stop) { [array removeObjectAtIndex:idx]; }];
18
- }
19
-
20
- typedef NS_ENUM(NSInteger, EditOverlap) {
21
- EditOverlapBeforeEdit,
22
- EditOverlapAfterEdit,
23
- EditOverlapFullyDeleted,
24
- EditOverlapDeletedInside,
25
- EditOverlapClippedEnd,
26
- EditOverlapClippedStart,
27
- };
28
-
29
- static EditOverlap classifyOverlap(NSUInteger rangeStart, NSUInteger rangeEnd, NSUInteger editLocation,
30
- NSUInteger deleteEnd)
31
- {
32
- if (rangeEnd <= editLocation)
33
- return EditOverlapBeforeEdit;
34
- if (rangeStart >= deleteEnd)
35
- return EditOverlapAfterEdit;
36
- if (rangeStart >= editLocation && rangeEnd <= deleteEnd)
37
- return EditOverlapFullyDeleted;
38
- if (rangeStart < editLocation && rangeEnd > deleteEnd)
39
- return EditOverlapDeletedInside;
40
- if (rangeStart < editLocation && rangeEnd <= deleteEnd)
41
- return EditOverlapClippedEnd;
42
- return EditOverlapClippedStart;
43
- }
2
+ #import "ENRMRangeEditAdjustment.h"
3
+ #import "ENRMRangeStoreUtils.h"
44
4
 
45
5
  @implementation ENRMFormattingStore {
46
6
  NSMutableArray<ENRMFormattingRange *> *_ranges;
@@ -148,6 +108,59 @@ static EditOverlap classifyOverlap(NSUInteger rangeStart, NSUInteger rangeEnd, N
148
108
  containingPosition:position - 1] != nil;
149
109
  }
150
110
 
111
+ - (BOOL)isStyleFullyActive:(ENRMInputStyleType)type inRange:(NSRange)range
112
+ {
113
+ NSUInteger pos = range.location;
114
+ NSUInteger end = NSMaxRange(range);
115
+ while (pos < end) {
116
+ ENRMFormattingRange *match = [self rangeOfType:type containingPosition:pos];
117
+ if (match == nil) {
118
+ return NO;
119
+ }
120
+ pos = NSMaxRange(match.range);
121
+ }
122
+ return YES;
123
+ }
124
+
125
+ - (BOOL)toggleStyle:(ENRMInputStyleType)type
126
+ inRange:(NSRange)range
127
+ conflictingStyles:(NSSet<NSNumber *> *)conflictingStyles
128
+ {
129
+ BOOL wasActive;
130
+ if (range.length > 0) {
131
+ wasActive = [self isStyleFullyActive:type inRange:range];
132
+ if (wasActive) {
133
+ [self removeType:type inRange:range];
134
+ } else {
135
+ for (NSNumber *conflict in conflictingStyles) {
136
+ [self removeType:(ENRMInputStyleType)conflict.integerValue inRange:range];
137
+ }
138
+ [self addRange:[ENRMFormattingRange rangeWithType:type range:range]];
139
+ }
140
+ } else {
141
+ wasActive = [self isStyleActive:type atPosition:range.location];
142
+ }
143
+ return wasActive;
144
+ }
145
+
146
+ - (BOOL)isToggleBlocked:(ENRMInputStyleType)type
147
+ atPosition:(NSUInteger)position
148
+ blockingStyles:(NSSet<NSNumber *> *)blockingStyles
149
+ {
150
+ if (blockingStyles.count == 0) {
151
+ return NO;
152
+ }
153
+ if ([self isStyleActive:type atPosition:position]) {
154
+ return NO;
155
+ }
156
+ for (NSNumber *blocker in blockingStyles) {
157
+ if ([self isStyleActive:(ENRMInputStyleType)blocker.integerValue atPosition:position]) {
158
+ return YES;
159
+ }
160
+ }
161
+ return NO;
162
+ }
163
+
151
164
  - (void)addRange:(ENRMFormattingRange *)newRange
152
165
  {
153
166
  NSMutableIndexSet *mergeIndexes = [NSMutableIndexSet indexSet];
@@ -167,13 +180,14 @@ static EditOverlap classifyOverlap(NSUInteger rangeStart, NSUInteger rangeEnd, N
167
180
  }
168
181
  }
169
182
 
170
- removeIndexesInReverse(_ranges, mergeIndexes);
183
+ ENRMRemoveIndexesInReverse(_ranges, mergeIndexes);
171
184
 
172
185
  ENRMFormattingRange *merged = [ENRMFormattingRange rangeWithType:newRange.type
173
186
  range:NSMakeRange(mergedStart, mergedEnd - mergedStart)
174
187
  url:newRange.url];
175
188
 
176
- NSUInteger insertAt = sortedInsertionIndex(_ranges, merged.range.location);
189
+ NSUInteger insertAt = ENRMSortedInsertionIndex(
190
+ _ranges, merged.range.location, ^NSUInteger(id range) { return ((ENRMFormattingRange *)range).range.location; });
177
191
  [_ranges insertObject:merged atIndex:insertAt];
178
192
  }
179
193
 
@@ -211,11 +225,13 @@ static EditOverlap classifyOverlap(NSUInteger rangeStart, NSUInteger rangeEnd, N
211
225
  }
212
226
  }
213
227
 
214
- removeIndexesInReverse(_ranges, indexesToRemove);
228
+ ENRMRemoveIndexesInReverse(_ranges, indexesToRemove);
215
229
 
216
230
  // Remainders are fragments of a just-removed range and cannot overlap others.
217
231
  for (ENRMFormattingRange *remainder in remainders) {
218
- NSUInteger insertAt = sortedInsertionIndex(_ranges, remainder.range.location);
232
+ NSUInteger insertAt = ENRMSortedInsertionIndex(_ranges, remainder.range.location, ^NSUInteger(id range) {
233
+ return ((ENRMFormattingRange *)range).range.location;
234
+ });
219
235
  [_ranges insertObject:remainder atIndex:insertAt];
220
236
  }
221
237
  }
@@ -232,71 +248,20 @@ static EditOverlap classifyOverlap(NSUInteger rangeStart, NSUInteger rangeEnd, N
232
248
  if (deletedLength == 0 && insertedLength == 0)
233
249
  return;
234
250
 
235
- NSUInteger deleteEnd = editLocation + deletedLength;
236
251
  NSMutableIndexSet *indexesToRemove = [NSMutableIndexSet indexSet];
237
252
 
238
253
  for (NSUInteger idx = 0; idx < _ranges.count; idx++) {
239
254
  ENRMFormattingRange *formattingRange = _ranges[idx];
240
- NSUInteger rangeStart = formattingRange.range.location;
241
- NSUInteger rangeEnd = NSMaxRange(formattingRange.range);
242
-
243
- if (deletedLength > 0) {
244
- EditOverlap overlap = classifyOverlap(rangeStart, rangeEnd, editLocation, deleteEnd);
245
-
246
- switch (overlap) {
247
- case EditOverlapBeforeEdit:
248
- break;
249
-
250
- case EditOverlapAfterEdit:
251
- formattingRange.range =
252
- NSMakeRange(rangeStart - deletedLength + insertedLength, formattingRange.range.length);
253
- break;
254
-
255
- case EditOverlapFullyDeleted:
256
- [indexesToRemove addIndex:idx];
257
- break;
258
-
259
- case EditOverlapDeletedInside: {
260
- NSUInteger newLength = formattingRange.range.length - deletedLength + insertedLength;
261
- formattingRange.range = NSMakeRange(rangeStart, newLength);
262
- break;
263
- }
264
-
265
- case EditOverlapClippedEnd: {
266
- NSUInteger newEnd = editLocation + insertedLength;
267
- NSUInteger newLength = newEnd > rangeStart ? newEnd - rangeStart : 0;
268
- formattingRange.range = NSMakeRange(rangeStart, newLength);
269
- if (newLength == 0) {
270
- [indexesToRemove addIndex:idx];
271
- }
272
- break;
273
- }
274
-
275
- case EditOverlapClippedStart: {
276
- NSUInteger charsClipped = deleteEnd - rangeStart;
277
- NSUInteger newStart = editLocation + insertedLength;
278
- NSUInteger newLength = formattingRange.range.length - charsClipped;
279
- formattingRange.range = NSMakeRange(newStart, newLength);
280
- if (newLength == 0) {
281
- [indexesToRemove addIndex:idx];
282
- }
283
- break;
284
- }
285
- }
286
- } else {
287
- if (rangeStart >= editLocation) {
288
- // Insertion at or before the range start: shift right.
289
- // _pendingStyles handles whether the inserted text inherits the style.
290
- formattingRange.range = NSMakeRange(rangeStart + insertedLength, formattingRange.range.length);
291
- } else if (editLocation < rangeEnd) {
292
- formattingRange.range = NSMakeRange(rangeStart, formattingRange.range.length + insertedLength);
293
- }
294
- // Typing at rangeEnd does not expand — pending styles control
295
- // whether new text at the boundary inherits the style.
255
+ BOOL inheritsReplacement = formattingRange.type != ENRMInputStyleTypeLink;
256
+ ENRMAdjustedRange adjusted = ENRMAdjustRangeForEdit(formattingRange.range, editLocation, deletedLength,
257
+ insertedLength, inheritsReplacement, NO);
258
+ formattingRange.range = adjusted.range;
259
+ if (adjusted.shouldRemove) {
260
+ [indexesToRemove addIndex:idx];
296
261
  }
297
262
  }
298
263
 
299
- removeIndexesInReverse(_ranges, indexesToRemove);
264
+ ENRMRemoveIndexesInReverse(_ranges, indexesToRemove);
300
265
 
301
266
  NSMutableIndexSet *emptyIndexes = [NSMutableIndexSet indexSet];
302
267
  for (NSUInteger idx = 0; idx < _ranges.count; idx++) {
@@ -305,7 +270,32 @@ static EditOverlap classifyOverlap(NSUInteger rangeStart, NSUInteger rangeEnd, N
305
270
  }
306
271
  }
307
272
  if (emptyIndexes.count > 0) {
308
- removeIndexesInReverse(_ranges, emptyIndexes);
273
+ ENRMRemoveIndexesInReverse(_ranges, emptyIndexes);
274
+ }
275
+
276
+ [self coalesceAdjacentSameTypeRanges];
277
+ }
278
+
279
+ /// Merge same-type (and same-url) ranges left adjacent or overlapping by an
280
+ /// edit — e.g. deleting the space in "**foo** **bar**" leaves two touching
281
+ /// bold ranges that would serialize as "**foo****bar**". `addRange:` keeps
282
+ /// this invariant on insert; the edit path must too.
283
+ - (void)coalesceAdjacentSameTypeRanges
284
+ {
285
+ for (NSUInteger idx = 0; idx < _ranges.count; idx++) {
286
+ ENRMFormattingRange *current = _ranges[idx];
287
+ NSUInteger next = idx + 1;
288
+ while (next < _ranges.count && _ranges[next].range.location <= NSMaxRange(current.range)) {
289
+ ENRMFormattingRange *candidate = _ranges[next];
290
+ BOOL sameUrl = (current.url == candidate.url) || [current.url isEqualToString:candidate.url];
291
+ if (candidate.type == current.type && sameUrl) {
292
+ NSUInteger mergedEnd = MAX(NSMaxRange(current.range), NSMaxRange(candidate.range));
293
+ current.range = NSMakeRange(current.range.location, mergedEnd - current.range.location);
294
+ [_ranges removeObjectAtIndex:next];
295
+ } else {
296
+ next++;
297
+ }
298
+ }
309
299
  }
310
300
  }
311
301