@apollohg/react-native-rich-text-editor 2.0.0

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 (494) hide show
  1. package/LICENSE +160 -0
  2. package/README.md +259 -0
  3. package/RUST-STANDARD-LIBRARY-NOTICES.html +8266 -0
  4. package/ReactNativeProseEditor.podspec +59 -0
  5. package/THIRD_PARTY_NOTICES.md +31155 -0
  6. package/android/build.gradle +188 -0
  7. package/android/consumer-rules.pro +18 -0
  8. package/android/expo/build.gradle +17 -0
  9. package/android/src/debug/java/com/apollohg/editor/viewer/PreparedProseDrawInstrumentation.kt +7 -0
  10. package/android/src/main/assets/editor-icons/MaterialIcons.json +2236 -0
  11. package/android/src/main/assets/editor-icons/MaterialIcons.ttf +0 -0
  12. package/android/src/main/java/com/apollohg/editor/AndroidApiCompat.kt +19 -0
  13. package/android/src/main/java/com/apollohg/editor/AndroidCollaborationTransport.kt +860 -0
  14. package/android/src/main/java/com/apollohg/editor/CaretGeometry.kt +91 -0
  15. package/android/src/main/java/com/apollohg/editor/CodeHighlighting.kt +141 -0
  16. package/android/src/main/java/com/apollohg/editor/DecodedBitmapBudget.kt +250 -0
  17. package/android/src/main/java/com/apollohg/editor/EditorAddons.kt +133 -0
  18. package/android/src/main/java/com/apollohg/editor/EditorBlockSpacing.kt +51 -0
  19. package/android/src/main/java/com/apollohg/editor/EditorBoxDrawable.kt +16 -0
  20. package/android/src/main/java/com/apollohg/editor/EditorBoxDrawing.kt +234 -0
  21. package/android/src/main/java/com/apollohg/editor/EditorCheckboxSpan.kt +87 -0
  22. package/android/src/main/java/com/apollohg/editor/EditorCodeHighlighting.kt +120 -0
  23. package/android/src/main/java/com/apollohg/editor/EditorDecorationLayer.java +18 -0
  24. package/android/src/main/java/com/apollohg/editor/EditorDocumentLayout.kt +626 -0
  25. package/android/src/main/java/com/apollohg/editor/EditorEditText.kt +1042 -0
  26. package/android/src/main/java/com/apollohg/editor/EditorEditTextAnnotations.kt +191 -0
  27. package/android/src/main/java/com/apollohg/editor/EditorEditTextCaret.kt +100 -0
  28. package/android/src/main/java/com/apollohg/editor/EditorEditTextClipboard.kt +101 -0
  29. package/android/src/main/java/com/apollohg/editor/EditorEditTextComposition.kt +220 -0
  30. package/android/src/main/java/com/apollohg/editor/EditorEditTextConfiguration.kt +316 -0
  31. package/android/src/main/java/com/apollohg/editor/EditorEditTextCorrection.kt +303 -0
  32. package/android/src/main/java/com/apollohg/editor/EditorEditTextDeferredUpdates.kt +327 -0
  33. package/android/src/main/java/com/apollohg/editor/EditorEditTextDeletion.kt +258 -0
  34. package/android/src/main/java/com/apollohg/editor/EditorEditTextDiagnostics.kt +83 -0
  35. package/android/src/main/java/com/apollohg/editor/EditorEditTextDragDrop.kt +67 -0
  36. package/android/src/main/java/com/apollohg/editor/EditorEditTextExternalComposition.kt +357 -0
  37. package/android/src/main/java/com/apollohg/editor/EditorEditTextHardwareInput.kt +277 -0
  38. package/android/src/main/java/com/apollohg/editor/EditorEditTextImages.kt +280 -0
  39. package/android/src/main/java/com/apollohg/editor/EditorEditTextInputLifecycle.kt +183 -0
  40. package/android/src/main/java/com/apollohg/editor/EditorEditTextInputPreparation.kt +79 -0
  41. package/android/src/main/java/com/apollohg/editor/EditorEditTextInputTraits.kt +384 -0
  42. package/android/src/main/java/com/apollohg/editor/EditorEditTextLayout.kt +100 -0
  43. package/android/src/main/java/com/apollohg/editor/EditorEditTextNativeMutation.kt +243 -0
  44. package/android/src/main/java/com/apollohg/editor/EditorEditTextPlaceholder.kt +154 -0
  45. package/android/src/main/java/com/apollohg/editor/EditorEditTextRenderPatch.kt +347 -0
  46. package/android/src/main/java/com/apollohg/editor/EditorEditTextRendering.kt +313 -0
  47. package/android/src/main/java/com/apollohg/editor/EditorEditTextRustCommands.kt +281 -0
  48. package/android/src/main/java/com/apollohg/editor/EditorEditTextSelection.kt +352 -0
  49. package/android/src/main/java/com/apollohg/editor/EditorEditTextState.kt +113 -0
  50. package/android/src/main/java/com/apollohg/editor/EditorEditTextTaskMarkers.kt +92 -0
  51. package/android/src/main/java/com/apollohg/editor/EditorEditTextTextCommit.kt +327 -0
  52. package/android/src/main/java/com/apollohg/editor/EditorEditTextToolbar.kt +84 -0
  53. package/android/src/main/java/com/apollohg/editor/EditorEditTextUpdates.kt +245 -0
  54. package/android/src/main/java/com/apollohg/editor/EditorGlyphHeightCursorDrawable.kt +42 -0
  55. package/android/src/main/java/com/apollohg/editor/EditorHeightBehavior.kt +13 -0
  56. package/android/src/main/java/com/apollohg/editor/EditorInputConnection.kt +923 -0
  57. package/android/src/main/java/com/apollohg/editor/EditorInputCoordinates.kt +191 -0
  58. package/android/src/main/java/com/apollohg/editor/EditorInputCorrection.kt +107 -0
  59. package/android/src/main/java/com/apollohg/editor/EditorInputCursorGeometry.kt +128 -0
  60. package/android/src/main/java/com/apollohg/editor/EditorInputSnapshots.kt +134 -0
  61. package/android/src/main/java/com/apollohg/editor/EditorInputSurroundingDeletion.kt +321 -0
  62. package/android/src/main/java/com/apollohg/editor/EditorKeyboardToolbarView.kt +851 -0
  63. package/android/src/main/java/com/apollohg/editor/EditorMentionStyle.kt +192 -0
  64. package/android/src/main/java/com/apollohg/editor/EditorReconciliationWatcher.kt +46 -0
  65. package/android/src/main/java/com/apollohg/editor/EditorStyleSheet.kt +303 -0
  66. package/android/src/main/java/com/apollohg/editor/EditorStyleSheetSpans.kt +253 -0
  67. package/android/src/main/java/com/apollohg/editor/EditorSurfaceInputConnection.kt +67 -0
  68. package/android/src/main/java/com/apollohg/editor/EditorTextDecorationDrawing.kt +143 -0
  69. package/android/src/main/java/com/apollohg/editor/EditorTextSurface.kt +712 -0
  70. package/android/src/main/java/com/apollohg/editor/EditorTextSurfaceDragDrop.kt +94 -0
  71. package/android/src/main/java/com/apollohg/editor/EditorTextSurfaceInteraction.kt +708 -0
  72. package/android/src/main/java/com/apollohg/editor/EditorTheme.kt +650 -0
  73. package/android/src/main/java/com/apollohg/editor/EditorV2Adapter.kt +912 -0
  74. package/android/src/main/java/com/apollohg/editor/EditorV2AdapterMutations.kt +402 -0
  75. package/android/src/main/java/com/apollohg/editor/EditorV2AdapterRendering.kt +123 -0
  76. package/android/src/main/java/com/apollohg/editor/EditorV2AdapterSelection.kt +203 -0
  77. package/android/src/main/java/com/apollohg/editor/EditorV2Backend.kt +120 -0
  78. package/android/src/main/java/com/apollohg/editor/EditorV2Driver.kt +87 -0
  79. package/android/src/main/java/com/apollohg/editor/EditorV2Registry.kt +97 -0
  80. package/android/src/main/java/com/apollohg/editor/EditorV2RenderValidation.kt +409 -0
  81. package/android/src/main/java/com/apollohg/editor/ExpoAutoGrowStyleSizePublisher.kt +34 -0
  82. package/android/src/main/java/com/apollohg/editor/ImageResizeOverlayView.kt +266 -0
  83. package/android/src/main/java/com/apollohg/editor/ImeTextCoordinateMapper.kt +102 -0
  84. package/android/src/main/java/com/apollohg/editor/KeyboardToolbarImeAnimationController.kt +101 -0
  85. package/android/src/main/java/com/apollohg/editor/MentionSuggestionChipView.kt +234 -0
  86. package/android/src/main/java/com/apollohg/editor/NativeCollaborationTransportRegistry.kt +493 -0
  87. package/android/src/main/java/com/apollohg/editor/NativeEditorExpoView.kt +813 -0
  88. package/android/src/main/java/com/apollohg/editor/NativeEditorExpoViewAtoms.kt +68 -0
  89. package/android/src/main/java/com/apollohg/editor/NativeEditorExpoViewBinding.kt +126 -0
  90. package/android/src/main/java/com/apollohg/editor/NativeEditorExpoViewDiagnostics.kt +208 -0
  91. package/android/src/main/java/com/apollohg/editor/NativeEditorExpoViewErrors.kt +146 -0
  92. package/android/src/main/java/com/apollohg/editor/NativeEditorExpoViewEvents.kt +150 -0
  93. package/android/src/main/java/com/apollohg/editor/NativeEditorExpoViewExternalComposition.kt +39 -0
  94. package/android/src/main/java/com/apollohg/editor/NativeEditorExpoViewFocus.kt +176 -0
  95. package/android/src/main/java/com/apollohg/editor/NativeEditorExpoViewLifecycle.kt +302 -0
  96. package/android/src/main/java/com/apollohg/editor/NativeEditorExpoViewMentions.kt +259 -0
  97. package/android/src/main/java/com/apollohg/editor/NativeEditorExpoViewNativeActions.kt +179 -0
  98. package/android/src/main/java/com/apollohg/editor/NativeEditorExpoViewOutsideTap.kt +214 -0
  99. package/android/src/main/java/com/apollohg/editor/NativeEditorExpoViewPendingUpdates.kt +376 -0
  100. package/android/src/main/java/com/apollohg/editor/NativeEditorExpoViewProperties.kt +234 -0
  101. package/android/src/main/java/com/apollohg/editor/NativeEditorExpoViewPropertyRetries.kt +197 -0
  102. package/android/src/main/java/com/apollohg/editor/NativeEditorExpoViewToolbar.kt +285 -0
  103. package/android/src/main/java/com/apollohg/editor/NativeEditorExpoViewTypes.kt +28 -0
  104. package/android/src/main/java/com/apollohg/editor/NativeEditorExpoViewUpdates.kt +271 -0
  105. package/android/src/main/java/com/apollohg/editor/NativeEditorModule.kt +687 -0
  106. package/android/src/main/java/com/apollohg/editor/NativeEditorOutsideTapDispatcher.kt +380 -0
  107. package/android/src/main/java/com/apollohg/editor/NativeEditorV2Numbers.kt +45 -0
  108. package/android/src/main/java/com/apollohg/editor/NativeEditorViewRegistry.kt +372 -0
  109. package/android/src/main/java/com/apollohg/editor/NativeImagePipeline.kt +22 -0
  110. package/android/src/main/java/com/apollohg/editor/NativeToolbar.kt +193 -0
  111. package/android/src/main/java/com/apollohg/editor/NativeToolbarIcons.kt +177 -0
  112. package/android/src/main/java/com/apollohg/editor/NativeToolbarItem.kt +274 -0
  113. package/android/src/main/java/com/apollohg/editor/OkHttpCollaborationSocket.kt +102 -0
  114. package/android/src/main/java/com/apollohg/editor/OrderedListMarkerFormatter.kt +130 -0
  115. package/android/src/main/java/com/apollohg/editor/PointerTransparentView.java +18 -0
  116. package/android/src/main/java/com/apollohg/editor/PositionBridge.kt +128 -0
  117. package/android/src/main/java/com/apollohg/editor/ProseViewerView.kt +854 -0
  118. package/android/src/main/java/com/apollohg/editor/RemoteSelectionOverlayView.kt +314 -0
  119. package/android/src/main/java/com/apollohg/editor/RenderBlockSpans.kt +314 -0
  120. package/android/src/main/java/com/apollohg/editor/RenderBridge.kt +224 -0
  121. package/android/src/main/java/com/apollohg/editor/RenderBridgeBlockStyles.kt +407 -0
  122. package/android/src/main/java/com/apollohg/editor/RenderBridgeElements.kt +544 -0
  123. package/android/src/main/java/com/apollohg/editor/RenderBridgeInlineAndAtoms.kt +631 -0
  124. package/android/src/main/java/com/apollohg/editor/RenderBridgeParagraphs.kt +215 -0
  125. package/android/src/main/java/com/apollohg/editor/RenderImageDecoder.kt +748 -0
  126. package/android/src/main/java/com/apollohg/editor/RenderImageLoader.kt +900 -0
  127. package/android/src/main/java/com/apollohg/editor/RenderLayoutConstants.kt +117 -0
  128. package/android/src/main/java/com/apollohg/editor/RenderMediaSpans.kt +337 -0
  129. package/android/src/main/java/com/apollohg/editor/RenderParagraphSpans.kt +182 -0
  130. package/android/src/main/java/com/apollohg/editor/RichTextEditorView.kt +951 -0
  131. package/android/src/main/java/com/apollohg/editor/SharedNativeImagePipeline.kt +78 -0
  132. package/android/src/main/java/com/apollohg/editor/UniffiEditorV2Backend.kt +261 -0
  133. package/android/src/main/java/com/apollohg/editor/viewer/AndroidProseLayoutEngine.kt +1656 -0
  134. package/android/src/main/java/com/apollohg/editor/viewer/FabricAttachmentSidecars.kt +80 -0
  135. package/android/src/main/java/com/apollohg/editor/viewer/FabricLeaseHandleBridge.kt +59 -0
  136. package/android/src/main/java/com/apollohg/editor/viewer/FallbackSelectionGeometry.kt +450 -0
  137. package/android/src/main/java/com/apollohg/editor/viewer/PreparedProseDrawingView.kt +678 -0
  138. package/android/src/main/java/com/apollohg/editor/viewer/PreparedProseInstrumentation.kt +608 -0
  139. package/android/src/main/java/com/apollohg/editor/viewer/PreparedProseLayout.kt +186 -0
  140. package/android/src/main/java/com/apollohg/editor/viewer/PreparedProseLayoutCache.kt +393 -0
  141. package/android/src/main/java/com/apollohg/editor/viewer/PreparedProseLayoutRegistry.kt +828 -0
  142. package/android/src/main/java/com/apollohg/editor/viewer/PreparedProseTheme.kt +316 -0
  143. package/android/src/main/java/com/apollohg/editor/viewer/PreparedProseViewerManager.kt +900 -0
  144. package/android/src/main/java/com/apollohg/editor/viewer/PreparedProseViewerPackage.kt +16 -0
  145. package/android/src/main/java/com/apollohg/editor/viewer/PreparedViewerAtoms.kt +89 -0
  146. package/android/src/main/java/com/apollohg/editor/viewer/ViewerCodeHighlighting.kt +91 -0
  147. package/android/src/main/java/com/apollohg/editor/viewer/ViewerDocument.kt +453 -0
  148. package/android/src/main/java/com/apollohg/editor/viewer/ViewerFontEnvironment.kt +282 -0
  149. package/android/src/main/java/com/apollohg/editor/viewer/ViewerImagePipeline.kt +460 -0
  150. package/android/src/main/jni/CMakeLists.txt +85 -0
  151. package/android/src/main/jni/PreparedProseViewerMeasurementsManager.cpp +334 -0
  152. package/android/src/main/jni/ReactNativeProseEditorSpec.h +17 -0
  153. package/android/src/main/jni/reactnativeproseeditor.h +6 -0
  154. package/android/src/main/res/values/attrs.xml +6 -0
  155. package/android/src/release/java/com/apollohg/editor/viewer/PreparedProseDrawInstrumentation.kt +9 -0
  156. package/app.plugin.js +62 -0
  157. package/common/cpp/react/renderer/components/PreparedProseViewer/PreparedProseMeasurementsManager.h +62 -0
  158. package/common/cpp/react/renderer/components/PreparedProseViewer/PreparedProseViewerComponentDescriptor.h +30 -0
  159. package/common/cpp/react/renderer/components/PreparedProseViewer/PreparedProseViewerShadowNode.cpp +192 -0
  160. package/common/cpp/react/renderer/components/PreparedProseViewer/PreparedProseViewerShadowNode.h +46 -0
  161. package/common/cpp/react/renderer/components/PreparedProseViewer/PreparedProseViewerState.h +145 -0
  162. package/dist/AtomHost.d.ts +17 -0
  163. package/dist/AtomHost.js +135 -0
  164. package/dist/DefaultAtomChip.d.ts +2 -0
  165. package/dist/DefaultAtomChip.js +22 -0
  166. package/dist/EditorAddon.d.ts +32 -0
  167. package/dist/EditorAddon.js +29 -0
  168. package/dist/EditorAddonNormalization.d.ts +6 -0
  169. package/dist/EditorAddonNormalization.js +48 -0
  170. package/dist/EditorMentionThemeNormalization.d.ts +8 -0
  171. package/dist/EditorMentionThemeNormalization.js +22 -0
  172. package/dist/EditorMentionThemeValidation.d.ts +12 -0
  173. package/dist/EditorMentionThemeValidation.js +95 -0
  174. package/dist/EditorStyleSheet.d.ts +4 -0
  175. package/dist/EditorStyleSheet.js +10 -0
  176. package/dist/EditorStyleSheetNormalization.d.ts +3 -0
  177. package/dist/EditorStyleSheetNormalization.js +226 -0
  178. package/dist/EditorStyleSheetTypes.d.ts +151 -0
  179. package/dist/EditorStyleSheetTypes.js +2 -0
  180. package/dist/EditorTheme.d.ts +117 -0
  181. package/dist/EditorTheme.js +41 -0
  182. package/dist/EditorToolbar.d.ts +4 -0
  183. package/dist/EditorToolbar.js +17 -0
  184. package/dist/EditorToolbarComponent.d.ts +13 -0
  185. package/dist/EditorToolbarComponent.js +24 -0
  186. package/dist/EditorToolbarItems.d.ts +9 -0
  187. package/dist/EditorToolbarItems.js +58 -0
  188. package/dist/EditorToolbarRegistry.d.ts +59 -0
  189. package/dist/EditorToolbarRegistry.js +175 -0
  190. package/dist/EditorToolbarTypes.d.ts +273 -0
  191. package/dist/EditorToolbarTypes.js +2 -0
  192. package/dist/EditorToolbarVisuals.d.ts +154 -0
  193. package/dist/EditorToolbarVisuals.js +228 -0
  194. package/dist/EditorUpdateRevision.d.ts +8 -0
  195. package/dist/EditorUpdateRevision.js +22 -0
  196. package/dist/ExternalTextComposition.d.ts +45 -0
  197. package/dist/ExternalTextComposition.js +537 -0
  198. package/dist/ImageLoadingPolicy.d.ts +54 -0
  199. package/dist/ImageLoadingPolicy.js +60 -0
  200. package/dist/NativeEditorBoundaryError.d.ts +111 -0
  201. package/dist/NativeEditorBoundaryError.js +268 -0
  202. package/dist/NativeEditorBridge.d.ts +9 -0
  203. package/dist/NativeEditorBridge.js +37 -0
  204. package/dist/NativeEditorCollaborationTransport.d.ts +154 -0
  205. package/dist/NativeEditorCollaborationTransport.js +275 -0
  206. package/dist/NativeEditorCreateConfig.d.ts +16 -0
  207. package/dist/NativeEditorCreateConfig.js +249 -0
  208. package/dist/NativeEditorCreateJson.d.ts +76 -0
  209. package/dist/NativeEditorCreateJson.js +474 -0
  210. package/dist/NativeEditorCreateValidation.d.ts +32 -0
  211. package/dist/NativeEditorCreateValidation.js +150 -0
  212. package/dist/NativeEditorDocumentBridge.d.ts +72 -0
  213. package/dist/NativeEditorDocumentBridge.js +305 -0
  214. package/dist/NativeEditorDocumentHandle.d.ts +70 -0
  215. package/dist/NativeEditorDocumentHandle.js +89 -0
  216. package/dist/NativeEditorLocalAwareness.d.ts +34 -0
  217. package/dist/NativeEditorLocalAwareness.js +153 -0
  218. package/dist/NativeEditorNativeModule.d.ts +48 -0
  219. package/dist/NativeEditorNativeModule.js +34 -0
  220. package/dist/NativeEditorRenderNormalization.d.ts +22 -0
  221. package/dist/NativeEditorRenderNormalization.js +274 -0
  222. package/dist/NativeEditorResultNormalization.d.ts +108 -0
  223. package/dist/NativeEditorResultNormalization.js +400 -0
  224. package/dist/NativeEditorTypes.d.ts +318 -0
  225. package/dist/NativeEditorTypes.js +15 -0
  226. package/dist/NativeEditorV2Decimal.d.ts +5 -0
  227. package/dist/NativeEditorV2Decimal.js +18 -0
  228. package/dist/NativeProseViewer.d.ts +122 -0
  229. package/dist/NativeProseViewer.js +130 -0
  230. package/dist/NativeRichTextEditor.d.ts +3 -0
  231. package/dist/NativeRichTextEditor.js +6 -0
  232. package/dist/ResourceLimits.d.ts +100 -0
  233. package/dist/ResourceLimits.js +80 -0
  234. package/dist/RichTextEditor.d.ts +4 -0
  235. package/dist/RichTextEditor.js +25 -0
  236. package/dist/RichTextEditorNativeTypes.d.ts +122 -0
  237. package/dist/RichTextEditorNativeTypes.js +2 -0
  238. package/dist/RichTextEditorNativeView.d.ts +12 -0
  239. package/dist/RichTextEditorNativeView.js +15 -0
  240. package/dist/RichTextEditorSerialization.d.ts +53 -0
  241. package/dist/RichTextEditorSerialization.js +283 -0
  242. package/dist/RichTextEditorTypes.d.ts +281 -0
  243. package/dist/RichTextEditorTypes.js +2 -0
  244. package/dist/ViewerConfiguration.d.ts +22 -0
  245. package/dist/ViewerConfiguration.js +6 -0
  246. package/dist/YjsCollaboration.d.ts +146 -0
  247. package/dist/YjsCollaboration.js +496 -0
  248. package/dist/addons.d.ts +193 -0
  249. package/dist/addons.js +122 -0
  250. package/dist/atomConstants.d.ts +3 -0
  251. package/dist/atomConstants.js +6 -0
  252. package/dist/atomInstances.d.ts +35 -0
  253. package/dist/atomInstances.js +79 -0
  254. package/dist/atomPolicy.d.ts +4 -0
  255. package/dist/atomPolicy.js +47 -0
  256. package/dist/atomUpdates.d.ts +2 -0
  257. package/dist/atomUpdates.js +38 -0
  258. package/dist/atoms.d.ts +92 -0
  259. package/dist/atoms.js +222 -0
  260. package/dist/attributeValidation.d.ts +4 -0
  261. package/dist/attributeValidation.js +97 -0
  262. package/dist/contentExpression.d.ts +6 -0
  263. package/dist/contentExpression.js +335 -0
  264. package/dist/index.d.ts +21 -0
  265. package/dist/index.js +78 -0
  266. package/dist/listMarkers.d.ts +15 -0
  267. package/dist/listMarkers.js +21 -0
  268. package/dist/schemaDefinition.d.ts +143 -0
  269. package/dist/schemaDefinition.js +206 -0
  270. package/dist/schemaDocument.d.ts +17 -0
  271. package/dist/schemaDocument.js +69 -0
  272. package/dist/schemaDocumentConstruction.d.ts +5 -0
  273. package/dist/schemaDocumentConstruction.js +125 -0
  274. package/dist/schemaNormalization.d.ts +29 -0
  275. package/dist/schemaNormalization.js +313 -0
  276. package/dist/schemaPresets.d.ts +68 -0
  277. package/dist/schemaPresets.js +198 -0
  278. package/dist/schemaResolution.d.ts +9 -0
  279. package/dist/schemaResolution.js +211 -0
  280. package/dist/schemas.d.ts +5 -0
  281. package/dist/schemas.js +28 -0
  282. package/dist/specs/PreparedProseViewerNativeComponent.d.ts +37 -0
  283. package/dist/specs/PreparedProseViewerNativeComponent.js +6 -0
  284. package/dist/useEditorToolbarInteractions.d.ts +12 -0
  285. package/dist/useEditorToolbarInteractions.js +218 -0
  286. package/dist/useEditorToolbarItems.d.ts +8 -0
  287. package/dist/useEditorToolbarItems.js +280 -0
  288. package/dist/useEditorToolbarPresentation.d.ts +4 -0
  289. package/dist/useEditorToolbarPresentation.js +203 -0
  290. package/dist/useEditorToolbarState.d.ts +63 -0
  291. package/dist/useEditorToolbarState.js +108 -0
  292. package/dist/useFocusPreservingFrames.d.ts +17 -0
  293. package/dist/useFocusPreservingFrames.js +108 -0
  294. package/dist/useNativeEditor.d.ts +66 -0
  295. package/dist/useNativeEditor.js +370 -0
  296. package/dist/useRichTextEditorCommands.d.ts +21 -0
  297. package/dist/useRichTextEditorCommands.js +299 -0
  298. package/dist/useRichTextEditorEvents.d.ts +18 -0
  299. package/dist/useRichTextEditorEvents.js +216 -0
  300. package/dist/useRichTextEditorMentions.d.ts +11 -0
  301. package/dist/useRichTextEditorMentions.js +316 -0
  302. package/dist/useRichTextEditorPresentation.d.ts +5 -0
  303. package/dist/useRichTextEditorPresentation.js +178 -0
  304. package/dist/useRichTextEditorState.d.ts +180 -0
  305. package/dist/useRichTextEditorState.js +405 -0
  306. package/dist/useRichTextEditorUpdates.d.ts +10 -0
  307. package/dist/useRichTextEditorUpdates.js +308 -0
  308. package/dist/useViewerAtoms.d.ts +38 -0
  309. package/dist/useViewerAtoms.js +288 -0
  310. package/expo-module.config.json +13 -0
  311. package/ios/EditorAddons.swift +354 -0
  312. package/ios/EditorCodeHighlighting.swift +184 -0
  313. package/ios/EditorCore.xcframework/Info.plist +44 -0
  314. package/ios/EditorCore.xcframework/ios-arm64/libeditor_core.a +0 -0
  315. package/ios/EditorCore.xcframework/ios-arm64_x86_64-simulator/libeditor_core.a +0 -0
  316. package/ios/EditorInteractionOverlays.swift +697 -0
  317. package/ios/EditorLayoutManager.swift +971 -0
  318. package/ios/EditorNodeTypes.swift +37 -0
  319. package/ios/EditorStyleSheet.swift +461 -0
  320. package/ios/EditorTextView+AttributedPatch.swift +305 -0
  321. package/ios/EditorTextView+Binding.swift +61 -0
  322. package/ios/EditorTextView+Caret.swift +333 -0
  323. package/ios/EditorTextView+Commands.swift +203 -0
  324. package/ios/EditorTextView+Delegate.swift +65 -0
  325. package/ios/EditorTextView+Diagnostics.swift +225 -0
  326. package/ios/EditorTextView+DragDrop.swift +290 -0
  327. package/ios/EditorTextView+ExternalComposition.swift +364 -0
  328. package/ios/EditorTextView+Images.swift +354 -0
  329. package/ios/EditorTextView+InputTraits.swift +200 -0
  330. package/ios/EditorTextView+KeyboardInput.swift +318 -0
  331. package/ios/EditorTextView+Layout.swift +245 -0
  332. package/ios/EditorTextView+MarkedText.swift +267 -0
  333. package/ios/EditorTextView+NativeInputLifecycle.swift +372 -0
  334. package/ios/EditorTextView+NativeMutation.swift +471 -0
  335. package/ios/EditorTextView+Reconciliation.swift +97 -0
  336. package/ios/EditorTextView+RenderPatch.swift +573 -0
  337. package/ios/EditorTextView+Rendering.swift +539 -0
  338. package/ios/EditorTextView+Selection.swift +542 -0
  339. package/ios/EditorTextView.swift +953 -0
  340. package/ios/EditorTheme.swift +626 -0
  341. package/ios/EditorV2Adapter+Commands.swift +204 -0
  342. package/ios/EditorV2Adapter+Envelope.swift +238 -0
  343. package/ios/EditorV2Adapter+Mutation.swift +392 -0
  344. package/ios/EditorV2Adapter+Registry.swift +185 -0
  345. package/ios/EditorV2Adapter+RenderState.swift +360 -0
  346. package/ios/EditorV2Adapter+RenderValidation.swift +420 -0
  347. package/ios/EditorV2Adapter+Selection.swift +329 -0
  348. package/ios/EditorV2Adapter+TextCommands.swift +430 -0
  349. package/ios/EditorV2Adapter.swift +376 -0
  350. package/ios/EditorV2Shadow.swift +353 -0
  351. package/ios/Generated_editor_core.swift +2378 -0
  352. package/ios/NativeCodeHighlighting.swift +159 -0
  353. package/ios/NativeCollaborationSocket.swift +144 -0
  354. package/ios/NativeCollaborationTransport+Protocol.swift +258 -0
  355. package/ios/NativeCollaborationTransport+Socket.swift +379 -0
  356. package/ios/NativeCollaborationTransport+Validation.swift +103 -0
  357. package/ios/NativeCollaborationTransport.swift +322 -0
  358. package/ios/NativeCollaborationTransportRegistry.swift +521 -0
  359. package/ios/NativeEditorExpoView+AccessoryRetry.swift +219 -0
  360. package/ios/NativeEditorExpoView+Binding.swift +268 -0
  361. package/ios/NativeEditorExpoView+Diagnostics.swift +66 -0
  362. package/ios/NativeEditorExpoView+Events.swift +131 -0
  363. package/ios/NativeEditorExpoView+Focus.swift +169 -0
  364. package/ios/NativeEditorExpoView+MentionRetry.swift +288 -0
  365. package/ios/NativeEditorExpoView+Mentions.swift +288 -0
  366. package/ios/NativeEditorExpoView+Properties.swift +300 -0
  367. package/ios/NativeEditorExpoView+Toolbar.swift +86 -0
  368. package/ios/NativeEditorExpoView+Updates.swift +312 -0
  369. package/ios/NativeEditorExpoView.swift +349 -0
  370. package/ios/NativeEditorModule.swift +856 -0
  371. package/ios/NativeEditorViewRegistry.swift +226 -0
  372. package/ios/NativeToolbar+ButtonStyle.swift +214 -0
  373. package/ios/NativeToolbar+Buttons.swift +228 -0
  374. package/ios/NativeToolbar+Diagnostics.swift +114 -0
  375. package/ios/NativeToolbar+Menu.swift +101 -0
  376. package/ios/NativeToolbar+Models.swift +519 -0
  377. package/ios/NativeToolbar+Placeholder.swift +39 -0
  378. package/ios/NativeToolbar.swift +612 -0
  379. package/ios/OrderedListMarkerFormatter.swift +103 -0
  380. package/ios/PositionBridge.swift +596 -0
  381. package/ios/ProseViewerView.swift +462 -0
  382. package/ios/RenderBridge+Atoms.swift +288 -0
  383. package/ios/RenderBridge+Attachments.swift +246 -0
  384. package/ios/RenderBridge+BlockBoundaries.swift +313 -0
  385. package/ios/RenderBridge+Style.swift +343 -0
  386. package/ios/RenderBridge.swift +704 -0
  387. package/ios/RichTextEditorView.swift +930 -0
  388. package/ios/SharedNativeImagePipeline+Cache.swift +189 -0
  389. package/ios/SharedNativeImagePipeline+Transport.swift +328 -0
  390. package/ios/SharedNativeImagePipeline.swift +533 -0
  391. package/ios/Viewer/CoreTextProseLayoutEngine+AttributedText.swift +436 -0
  392. package/ios/Viewer/CoreTextProseLayoutEngine+Models.swift +322 -0
  393. package/ios/Viewer/CoreTextProseLayoutEngine.swift +635 -0
  394. package/ios/Viewer/Fabric/PREPPreparedProseViewerComponentView.h +4 -0
  395. package/ios/Viewer/Fabric/PREPPreparedProseViewerComponentView.mm +767 -0
  396. package/ios/Viewer/Fabric/PreparedProseMeasurementsManager.mm +118 -0
  397. package/ios/Viewer/NativeSVGImageDecoder.h +9 -0
  398. package/ios/Viewer/NativeSVGImageDecoder.mm +106 -0
  399. package/ios/Viewer/NativeSVGPreflight.h +11 -0
  400. package/ios/Viewer/NativeSVGPreflight.mm +219 -0
  401. package/ios/Viewer/PreparedProseDrawingView.swift +639 -0
  402. package/ios/Viewer/PreparedProseInstrumentation.swift +387 -0
  403. package/ios/Viewer/PreparedProseLayout.swift +326 -0
  404. package/ios/Viewer/PreparedProseLayoutCache.swift +766 -0
  405. package/ios/Viewer/PreparedProseLayoutRegistry+Artifacts.swift +377 -0
  406. package/ios/Viewer/PreparedProseLayoutRegistry+Fabric.swift +582 -0
  407. package/ios/Viewer/PreparedProseLayoutRegistry+FabricOwnership.swift +128 -0
  408. package/ios/Viewer/PreparedProseLayoutRegistry.swift +381 -0
  409. package/ios/Viewer/ViewerDocument.swift +575 -0
  410. package/ios/Viewer/ViewerFontEnvironment.swift +283 -0
  411. package/ios/Viewer/ViewerImagePipeline.swift +478 -0
  412. package/ios/editor_coreFFI/editor_coreFFI.h +1023 -0
  413. package/ios/editor_coreFFI/module.modulemap +7 -0
  414. package/package.json +151 -0
  415. package/react-native.config.js +17 -0
  416. package/rust/android/arm64-v8a/libeditor_core.so +0 -0
  417. package/rust/android/armeabi-v7a/libeditor_core.so +0 -0
  418. package/rust/android/x86/libeditor_core.so +0 -0
  419. package/rust/android/x86_64/libeditor_core.so +0 -0
  420. package/rust/bindings/kotlin/uniffi/editor_core/editor_core.kt +3146 -0
  421. package/src/AtomHost.tsx +180 -0
  422. package/src/DefaultAtomChip.tsx +27 -0
  423. package/src/EditorAddon.ts +65 -0
  424. package/src/EditorAddonNormalization.ts +49 -0
  425. package/src/EditorMentionThemeNormalization.ts +25 -0
  426. package/src/EditorMentionThemeValidation.ts +133 -0
  427. package/src/EditorStyleSheet.ts +9 -0
  428. package/src/EditorStyleSheetNormalization.ts +219 -0
  429. package/src/EditorStyleSheetTypes.ts +189 -0
  430. package/src/EditorTheme.ts +196 -0
  431. package/src/EditorToolbar.tsx +31 -0
  432. package/src/EditorToolbarComponent.tsx +23 -0
  433. package/src/EditorToolbarItems.tsx +64 -0
  434. package/src/EditorToolbarRegistry.tsx +254 -0
  435. package/src/EditorToolbarTypes.tsx +322 -0
  436. package/src/EditorToolbarVisuals.tsx +270 -0
  437. package/src/EditorUpdateRevision.ts +26 -0
  438. package/src/ExternalTextComposition.ts +658 -0
  439. package/src/ImageLoadingPolicy.ts +125 -0
  440. package/src/NativeEditorBoundaryError.ts +345 -0
  441. package/src/NativeEditorBridge.ts +93 -0
  442. package/src/NativeEditorCollaborationTransport.ts +493 -0
  443. package/src/NativeEditorCreateConfig.ts +326 -0
  444. package/src/NativeEditorCreateJson.ts +579 -0
  445. package/src/NativeEditorCreateValidation.ts +178 -0
  446. package/src/NativeEditorDocumentBridge.ts +485 -0
  447. package/src/NativeEditorDocumentHandle.ts +168 -0
  448. package/src/NativeEditorLocalAwareness.ts +168 -0
  449. package/src/NativeEditorNativeModule.ts +97 -0
  450. package/src/NativeEditorRenderNormalization.ts +320 -0
  451. package/src/NativeEditorResultNormalization.ts +469 -0
  452. package/src/NativeEditorTypes.ts +366 -0
  453. package/src/NativeEditorV2Decimal.ts +13 -0
  454. package/src/NativeProseViewer.tsx +356 -0
  455. package/src/NativeRichTextEditor.tsx +33 -0
  456. package/src/ResourceLimits.ts +187 -0
  457. package/src/RichTextEditor.tsx +27 -0
  458. package/src/RichTextEditorNativeTypes.tsx +144 -0
  459. package/src/RichTextEditorNativeView.tsx +21 -0
  460. package/src/RichTextEditorSerialization.tsx +381 -0
  461. package/src/RichTextEditorTypes.tsx +327 -0
  462. package/src/ViewerConfiguration.ts +23 -0
  463. package/src/YjsCollaboration.ts +692 -0
  464. package/src/addons.ts +311 -0
  465. package/src/atomConstants.ts +3 -0
  466. package/src/atomInstances.ts +123 -0
  467. package/src/atomPolicy.ts +47 -0
  468. package/src/atomUpdates.ts +52 -0
  469. package/src/atoms.ts +379 -0
  470. package/src/attributeValidation.ts +116 -0
  471. package/src/contentExpression.ts +338 -0
  472. package/src/index.ts +295 -0
  473. package/src/listMarkers.ts +18 -0
  474. package/src/schemaDefinition.ts +395 -0
  475. package/src/schemaDocument.ts +92 -0
  476. package/src/schemaDocumentConstruction.ts +148 -0
  477. package/src/schemaNormalization.ts +367 -0
  478. package/src/schemaPresets.ts +250 -0
  479. package/src/schemaResolution.ts +242 -0
  480. package/src/schemas.ts +43 -0
  481. package/src/specs/PreparedProseViewerNativeComponent.ts +40 -0
  482. package/src/useEditorToolbarInteractions.tsx +329 -0
  483. package/src/useEditorToolbarItems.tsx +390 -0
  484. package/src/useEditorToolbarPresentation.tsx +483 -0
  485. package/src/useEditorToolbarState.tsx +172 -0
  486. package/src/useFocusPreservingFrames.ts +171 -0
  487. package/src/useNativeEditor.ts +534 -0
  488. package/src/useRichTextEditorCommands.tsx +478 -0
  489. package/src/useRichTextEditorEvents.tsx +342 -0
  490. package/src/useRichTextEditorMentions.tsx +441 -0
  491. package/src/useRichTextEditorPresentation.tsx +563 -0
  492. package/src/useRichTextEditorState.tsx +620 -0
  493. package/src/useRichTextEditorUpdates.tsx +403 -0
  494. package/src/useViewerAtoms.tsx +427 -0
@@ -0,0 +1,912 @@
1
+ package com.apollohg.editor
2
+
3
+ import org.json.JSONArray
4
+ import org.json.JSONObject
5
+
6
+ /**
7
+ * The v2 adapter.
8
+ *
9
+ * Owns one v2 editor session (decimal-string handle) and translates the
10
+ * existing native view operations into typed v2 transactions/results. Every
11
+ * mutation is one typed transaction against the tracked base document
12
+ * revision. Transient IME/composing state never reaches the adapter — only
13
+ * final commits do.
14
+ *
15
+ * Render derivation: the v2 render accessor
16
+ * ([EditorV2Backend.renderUpdate] / [EditorV2Backend.resolveScalarSelection]
17
+ * / [EditorV2Backend.docToScalar] / [EditorV2Backend.scalarToDoc]) returns
18
+ * everything the view needs — full render blocks, toolbar active state, the
19
+ * mirrored scalar selection resolved to doc positions, and the lenient
20
+ * doc↔scalar mapping (including the document's scalar extent) — derived
21
+ * directly from the live v2 session.
22
+ */
23
+ internal class EditorV2Adapter private constructor(
24
+ internal val backend: EditorV2Backend,
25
+ val editorId: String,
26
+ internal val roomBound: Boolean,
27
+ internal val collaborationWake: (String, CollaborationWakeReason) -> Unit
28
+ ) : EditorV2Driver {
29
+
30
+ var onAutonomousError: ((EditorV2Error) -> Unit)? = null
31
+
32
+ private data class AutonomousErrorOwner(
33
+ val token: Long,
34
+ val callback: (EditorV2Error) -> Unit,
35
+ val onReleased: () -> Unit
36
+ )
37
+
38
+ /** One live native-view binding exclusively owns autonomous errors. */
39
+ private var autonomousErrorOwner: AutonomousErrorOwner? = null
40
+
41
+ var baseDocumentRevision: ULong = 0uL
42
+ internal set
43
+
44
+ /** Paired with [baseDocumentRevision] by the same locked render read. */
45
+ var stateRevision: ULong = 0uL
46
+ internal set
47
+ private var nextRequestId: ULong = 0uL
48
+ internal var nativeOwnerId: String? = null
49
+ private var nativeOwnerToken: Long? = null
50
+ internal var positionEpoch: String? = null
51
+ internal var lastRequestIdForTesting: ULong? = null
52
+ private set
53
+ internal var backendEnvelopeCallCountForTesting = 0
54
+ private set
55
+ internal var lastSyncedScalarSelection: IntArray? = null
56
+ internal var cachedAuthoritativeScalarSelection: IntArray? = null
57
+ internal var cachedScalarLength: Int? = null
58
+ internal var cachedActiveState: JSONObject? = null
59
+ internal var cachedHistoryState: JSONObject? = null
60
+ internal var cachedViewUpdateJson: String? = null
61
+ internal var cachedAtomicRenderJson: String? = null
62
+ internal var cachedAtomicRenderDocumentRevision: ULong? = null
63
+ internal var renderUpdateCallCountForTesting = 0
64
+ internal set
65
+ internal var destroyed = false
66
+
67
+ /** Diagnostics for handled paths that never surface as error events. */
68
+ val debugNotes = mutableListOf<String>()
69
+
70
+ companion object {
71
+ /**
72
+ * Attach to an existing v2 session created through the module's
73
+ * JS-facing `editorV2Create` entry. The session is NOT re-created;
74
+ * the adapter routes the bound view's interactions through the
75
+ * shared session (the TS document handle and collaboration
76
+ * controller drive the same session over the module surface).
77
+ */
78
+ fun attach(
79
+ backend: EditorV2Backend,
80
+ editorId: String,
81
+ roomBound: Boolean,
82
+ collaborationWake: (String, CollaborationWakeReason) -> Unit = { id, reason ->
83
+ NativeCollaborationTransportRegistry.notifyOutboundAvailable(id, reason)
84
+ }
85
+ ): EditorV2Adapter? {
86
+ if (!isCanonicalDecimalEditorId(editorId)) return null
87
+ // Attachment establishes only that the handle is live. The first
88
+ // render adopts the revision, scalar extent, selection, active,
89
+ // and history caches as one locked snapshot before input resumes.
90
+ if (backend.getState(editorId) !is EditorV2CallResult.Ok) return null
91
+ return EditorV2Adapter(backend, editorId, roomBound, collaborationWake)
92
+ }
93
+
94
+ private fun isCanonicalDecimalEditorId(editorId: String): Boolean = editorId.isNotEmpty() &&
95
+ editorId.all { it in '0'..'9' } &&
96
+ (editorId == "0" || editorId.first() != '0') &&
97
+ editorId.toULongOrNull() != null
98
+
99
+ fun contractError(message: String): EditorV2Error =
100
+ EditorV2Error(domain = "boundary", code = "FFI_RESULT_INVALID", message = message)
101
+
102
+ internal fun destroyedError(): EditorV2Error = EditorV2Error(
103
+ domain = "lifecycle",
104
+ code = "ENGINE_DESTROYED",
105
+ message = "editor session is destroyed"
106
+ )
107
+ }
108
+
109
+ fun destroy(): EditorV2Error? {
110
+ if (destroyed) return null
111
+ nativeOwnerId?.let { backend.releaseNativeBinding(editorId, it) }
112
+ nativeOwnerId = null
113
+ nativeOwnerToken = null
114
+ positionEpoch = null
115
+ destroyed = true
116
+ val error = backend.destroy(editorId) ?: return null
117
+ if (error.code == "ENGINE_DESTROYED" || error.code == "ENGINE_DESTROYING") return null
118
+ return error
119
+ }
120
+
121
+ private fun requestIdExhaustedError(): EditorV2Error = EditorV2Error(
122
+ domain = "boundary",
123
+ code = "CONFIG_INVALID",
124
+ message = "v2 request id counter exhausted",
125
+ requestId = nextRequestId.toString(),
126
+ limit = ULong.MAX_VALUE.toString()
127
+ )
128
+
129
+ private fun buildEnvelope(
130
+ payload: JSONObject,
131
+ includeBaseRevision: Boolean = true
132
+ ): EditorV2CallResult<String> {
133
+ if (nextRequestId == ULong.MAX_VALUE) {
134
+ return EditorV2CallResult.Err(requestIdExhaustedError())
135
+ }
136
+ nextRequestId += 1u
137
+ lastRequestIdForTesting = nextRequestId
138
+ val parts = mutableListOf(
139
+ "\"version\":1",
140
+ "\"requestId\":${JSONObject.quote(nextRequestId.toString())}"
141
+ )
142
+ if (includeBaseRevision) {
143
+ parts.add(
144
+ "\"baseDocumentRevision\":${JSONObject.quote(baseDocumentRevision.toString())}"
145
+ )
146
+ }
147
+ val payloadJson = payload.toString()
148
+ if (payloadJson.length > 2) {
149
+ parts.add(payloadJson.substring(1, payloadJson.length - 1))
150
+ }
151
+ return EditorV2CallResult.Ok(
152
+ parts.joinToString(separator = ",", prefix = "{", postfix = "}")
153
+ )
154
+ }
155
+
156
+ internal fun callWithEnvelope(
157
+ payload: JSONObject,
158
+ includeBaseRevision: Boolean = true,
159
+ call: (String) -> EditorV2CallResult<String>
160
+ ): EditorV2CallResult<String> =
161
+ when (val envelope = buildEnvelope(payload, includeBaseRevision)) {
162
+ is EditorV2CallResult.Err -> envelope
163
+
164
+ is EditorV2CallResult.Ok -> {
165
+ backendEnvelopeCallCountForTesting += 1
166
+ call(envelope.value)
167
+ }
168
+ }
169
+
170
+ internal fun setNextRequestIdForTesting(requestId: ULong) {
171
+ nextRequestId = requestId
172
+ }
173
+
174
+ private fun positionEnvelope(scalar: Int, affinity: String? = null): JSONObject {
175
+ val envelope = JSONObject().put("offset", scalar).put("kind", "scalar")
176
+ if (affinity != null) envelope.put("affinity", affinity)
177
+ return envelope
178
+ }
179
+
180
+ internal fun selectionEnvelope(anchor: Int, head: Int, affinity: String): JSONObject =
181
+ JSONObject().put(
182
+ "selection",
183
+ JSONObject()
184
+ .put("type", "text")
185
+ .put("anchor", positionEnvelope(anchor, affinity))
186
+ .put("head", positionEnvelope(head, affinity))
187
+ )
188
+
189
+ internal fun bindAutonomousErrorOwner(
190
+ token: Long,
191
+ callback: (EditorV2Error) -> Unit,
192
+ onReleased: () -> Unit
193
+ ) {
194
+ val displaced = synchronized(this) {
195
+ autonomousErrorOwner.also {
196
+ autonomousErrorOwner = AutonomousErrorOwner(token, callback, onReleased)
197
+ }
198
+ }
199
+ claimNativeBinding(token, replaceExisting = true)
200
+ displaced?.onReleased?.invoke()
201
+ }
202
+
203
+ internal fun claimNativeBindingIfUnowned(token: Long) {
204
+ claimNativeBinding(token, replaceExisting = false)
205
+ }
206
+
207
+ internal fun isNativeBindingOwner(token: Long): Boolean = synchronized(this) {
208
+ nativeOwnerToken == token
209
+ }
210
+
211
+ private fun claimNativeBinding(token: Long, replaceExisting: Boolean) {
212
+ val releasedOwner = synchronized(this) {
213
+ if (!replaceExisting && nativeOwnerToken != null) return
214
+ if (nativeOwnerToken == token) return
215
+ nativeOwnerId.also {
216
+ nativeOwnerToken = token
217
+ nativeOwnerId = token.toString()
218
+ positionEpoch = null
219
+ }
220
+ }
221
+ releasedOwner?.let { backend.releaseNativeBinding(editorId, it) }
222
+ }
223
+
224
+ internal fun releaseNativeBindingOwner(token: Long) {
225
+ val releasedOwner = synchronized(this) {
226
+ if (nativeOwnerToken != token) return
227
+ nativeOwnerToken = null
228
+ positionEpoch = null
229
+ nativeOwnerId.also { nativeOwnerId = null }
230
+ }
231
+ releasedOwner?.let { backend.releaseNativeBinding(editorId, it) }
232
+ }
233
+
234
+ /** A stale view may clear only its own binding generation. */
235
+ internal fun clearAutonomousErrorOwner(token: Long) {
236
+ val released = synchronized(this) {
237
+ if (autonomousErrorOwner?.token == token) {
238
+ autonomousErrorOwner = null
239
+ true
240
+ } else {
241
+ false
242
+ }
243
+ }
244
+ if (released) releaseNativeBindingOwner(token)
245
+ }
246
+
247
+ /** Pair release invalidates the final owner even when no view remains registered. */
248
+ internal fun releaseAutonomousErrorOwner() {
249
+ val released = synchronized(this) {
250
+ autonomousErrorOwner.also {
251
+ autonomousErrorOwner = null
252
+ }
253
+ }
254
+ released?.let { releaseNativeBindingOwner(it.token) }
255
+ released?.onReleased?.invoke()
256
+ }
257
+
258
+ internal fun ownsAutonomousErrorOwner(token: Long): Boolean = synchronized(this) {
259
+ autonomousErrorOwner?.token == token
260
+ }
261
+
262
+ internal fun emit(error: EditorV2Error) {
263
+ debugNotes.add("emit ${error.domain}/${error.code}: ${error.message}")
264
+ val callback = synchronized(this) {
265
+ autonomousErrorOwner?.callback ?: onAutonomousError
266
+ }
267
+ callback?.invoke(error)
268
+ }
269
+
270
+ internal fun atomicRenderJson(matchingDocumentRevision: String): String? {
271
+ val revision = matchingDocumentRevision.toULongOrNull() ?: return null
272
+ if (cachedAtomicRenderDocumentRevision != revision) return null
273
+ return cachedAtomicRenderJson
274
+ }
275
+
276
+ @Volatile
277
+ internal var latestJSDrivenDocumentRevision: ULong = 0uL
278
+
279
+ private fun parseExternalReset(resetJson: String): JSONObject? {
280
+ val reset = try {
281
+ JSONObject(resetJson)
282
+ } catch (_: Exception) {
283
+ null
284
+ }
285
+ if (reset == null || reset.optString("history") != "resetAndClear" ||
286
+ reset.keys().asSequence().toSet() !=
287
+ setOf(
288
+ "history",
289
+ "documentRevision",
290
+ if (reset.has("setJson")) "setJson" else "setHtml"
291
+ ) ||
292
+ (reset.opt("setJson") !is JSONObject && reset.opt("setHtml") !is String) ||
293
+ canonicalV2U64(reset.opt("documentRevision") as? String) == null
294
+ ) {
295
+ emit(contractError("external reset intent is malformed"))
296
+ return null
297
+ }
298
+ return reset
299
+ }
300
+
301
+ internal fun validateExternalReset(resetJson: String): Boolean =
302
+ parseExternalReset(resetJson) != null
303
+
304
+ @Synchronized
305
+ internal fun adoptExternalReset(renderJson: String, resetJson: String): String? {
306
+ val reset = parseExternalReset(resetJson) ?: return null
307
+ val current = refreshFromRustState(null) ?: return null
308
+ if (parseAtomicRenderSnapshot(current)?.documentRevision ==
309
+ reset.getString("documentRevision").toULong()
310
+ ) {
311
+ return adoptExternalRender(renderJson)
312
+ }
313
+ if (latestJSDrivenDocumentRevision >
314
+ reset.getString("documentRevision").toULong()
315
+ ) {
316
+ return current
317
+ }
318
+ when (val result = backend.getState(editorId)) {
319
+ is EditorV2CallResult.Err -> {
320
+ emit(result.error)
321
+ return null
322
+ }
323
+
324
+ is EditorV2CallResult.Ok -> {
325
+ val origin = try {
326
+ JSONObject(result.value).getString("documentOrigin")
327
+ } catch (
328
+ _: Exception
329
+ ) {
330
+ null
331
+ }
332
+ if (origin == null) {
333
+ emit(contractError("v2 reset state violates the frozen shape"))
334
+ return null
335
+ }
336
+ if (origin != "nativeView") return refreshFromRustState(null)
337
+ }
338
+ }
339
+ reset.remove("documentRevision")
340
+ return when (
341
+ val result = callWithEnvelope(reset, includeBaseRevision = false) { requestJson ->
342
+ backend.replaceDocument(editorId, requestJson)
343
+ }
344
+ ) {
345
+ is EditorV2CallResult.Err -> {
346
+ emit(result.error)
347
+ null
348
+ }
349
+
350
+ is EditorV2CallResult.Ok -> {
351
+ val commit = try {
352
+ JSONObject(result.value)
353
+ } catch (_: Exception) {
354
+ null
355
+ }
356
+ if (commit?.opt("changed") !is Boolean ||
357
+ (commit.opt("documentRevision") as? String)?.toULongOrNull() == null
358
+ ) {
359
+ emit(contractError("v2 reset result violates the frozen shape"))
360
+ return null
361
+ }
362
+ val update = refreshFromRustState(null) ?: return null
363
+ if (commit.getBoolean("changed")) {
364
+ publishCachedCollaborationSelection()
365
+ notifyCollaborationMutation()
366
+ }
367
+ update
368
+ }
369
+ }
370
+ }
371
+
372
+ internal fun adoptExternalRender(renderJson: String): String? {
373
+ if (destroyed) {
374
+ emit(destroyedError())
375
+ return null
376
+ }
377
+ val snapshot = parseAtomicRenderSnapshot(renderJson)
378
+ if (snapshot == null) {
379
+ emit(contractError("v2 atomic render snapshot violates the frozen shape"))
380
+ return null
381
+ }
382
+ val resolvedPositionEpoch = when {
383
+ snapshot.positionEpoch != null -> snapshot.positionEpoch
384
+ nativeOwnerId == null -> positionEpoch
385
+ else -> pinPositionEpochCandidate(snapshot.documentRevision) ?: return null
386
+ }
387
+ val pinned = PinnedAtomicRenderSnapshot(snapshot, resolvedPositionEpoch)
388
+ return adopt(
389
+ pinned.snapshot,
390
+ stripViewSelection = false,
391
+ engineOwnedSelection = true,
392
+ resolvedPositionEpoch = pinned.positionEpoch
393
+ )
394
+ }
395
+
396
+ internal fun validateExternalRender(renderJson: String): Boolean {
397
+ if (destroyed) {
398
+ emit(destroyedError())
399
+ return false
400
+ }
401
+ if (parseAtomicRenderSnapshot(renderJson) != null) return true
402
+ emit(contractError("v2 atomic render snapshot violates the frozen shape"))
403
+ return false
404
+ }
405
+
406
+ override fun refreshFromRustState(mirrorSelection: IntArray?): String? =
407
+ // This result crosses the controlled-prop boundary, which admits only
408
+ // complete frozen atomic render snapshots. Its parse/adopt side effect
409
+ // updates adapter caches, but its public result must retain every
410
+ // validated wire field, including selection and scalarLength.
411
+ refreshInternal(
412
+ mirrorSelection,
413
+ stripViewSelection = false,
414
+ controlledPropSnapshot = true
415
+ )
416
+
417
+ internal fun recoverNativeRender(): String? {
418
+ val ownerId = synchronized(this) {
419
+ positionEpoch = null
420
+ nativeOwnerId
421
+ }
422
+ ownerId?.let { backend.releaseNativeBinding(editorId, it) }
423
+ return refreshInternal(null, stripViewSelection = false)
424
+ }
425
+
426
+ override fun currentStateJson(): String? =
427
+ refreshInternal(cachedAuthoritativeScalarSelection?.copyOf(), stripViewSelection = false)
428
+
429
+ override fun documentHtml(): String? {
430
+ if (destroyed) return null
431
+ return when (val result = backend.getDocumentHtml(editorId)) {
432
+ is EditorV2CallResult.Err -> {
433
+ emit(result.error)
434
+ null
435
+ }
436
+
437
+ is EditorV2CallResult.Ok -> try {
438
+ JSONObject(result.value).getString("html")
439
+ } catch (error: Exception) {
440
+ emit(contractError("v2 getDocumentHtml value violates the frozen shape"))
441
+ null
442
+ }
443
+ }
444
+ }
445
+
446
+ override fun documentJson(): String? {
447
+ if (destroyed) return null
448
+ return fetchDocumentJson()
449
+ }
450
+
451
+ override fun contentSnapshotJson(): String? {
452
+ if (destroyed) return null
453
+ return when (val result = backend.getContentSnapshot(editorId)) {
454
+ is EditorV2CallResult.Err -> {
455
+ emit(result.error)
456
+ null
457
+ }
458
+
459
+ is EditorV2CallResult.Ok -> result.value
460
+ }
461
+ }
462
+
463
+ override fun historyCanUndo(): Boolean? =
464
+ cachedHistoryState?.let { exactBool(it.opt("canUndo")) }
465
+
466
+ override fun historyCanRedo(): Boolean? =
467
+ cachedHistoryState?.let { exactBool(it.opt("canRedo")) }
468
+
469
+ override fun selectionJson(): String? {
470
+ val update =
471
+ refreshInternal(
472
+ cachedAuthoritativeScalarSelection?.copyOf(),
473
+ stripViewSelection = false
474
+ )
475
+ ?: return null
476
+ return try {
477
+ JSONObject(update).getJSONObject("selection").toString()
478
+ } catch (error: Exception) {
479
+ null
480
+ }
481
+ }
482
+
483
+ override fun syncSelection(anchor: Int, head: Int): EditorV2SelectionSync? {
484
+ if (destroyed) {
485
+ emit(destroyedError())
486
+ return null
487
+ }
488
+ if (nativeOwnerId != null) {
489
+ val previousDocumentRevision = baseDocumentRevision
490
+ val update =
491
+ performNativeIntent(nativeIntent("setSelection", anchor, head)).updateJsonOrNull()
492
+ ?: return null
493
+ val mapping = textDocumentSelection(update) ?: return null
494
+ publishCollaborationSelection(mapping[0], mapping[1])
495
+ return EditorV2SelectionSync(
496
+ mapping[0],
497
+ mapping[1],
498
+ update.takeIf { baseDocumentRevision != previousDocumentRevision }
499
+ )
500
+ }
501
+ var refreshedUpdateJson: String? = null
502
+ val mapping = when (val outcome = ensureSelection(anchor, head)) {
503
+ is SelectionSyncOutcome.Ok -> resolveSelectionMapping(anchor, head)
504
+
505
+ is SelectionSyncOutcome.Refreshed -> {
506
+ refreshedUpdateJson = outcome.updateJson
507
+ textDocumentSelection(outcome.updateJson)
508
+ }
509
+
510
+ is SelectionSyncOutcome.Failed -> return null
511
+ }
512
+ if (mapping == null) return null
513
+ publishCollaborationSelection(mapping[0], mapping[1])
514
+ return EditorV2SelectionSync(mapping[0], mapping[1], refreshedUpdateJson)
515
+ }
516
+
517
+ override fun syncSelectionQuiet(anchor: Int, head: Int): String? {
518
+ if (destroyed) return null
519
+ if (nativeOwnerId != null) {
520
+ val previousDocumentRevision = baseDocumentRevision
521
+ val update =
522
+ performNativeIntent(nativeIntent("setSelection", anchor, head)).updateJsonOrNull()
523
+ ?: return null
524
+ val mapping = textDocumentSelection(update) ?: return update
525
+ publishCollaborationSelection(mapping[0], mapping[1])
526
+ return update.takeIf { baseDocumentRevision != previousDocumentRevision }
527
+ }
528
+ var refreshedUpdateJson: String? = null
529
+ val mapping = when (val outcome = ensureSelection(anchor, head)) {
530
+ is SelectionSyncOutcome.Ok -> {
531
+ if (!roomBound) return null
532
+ val selection = lastSyncedScalarSelection ?: return null
533
+ resolveSelectionMapping(selection[0], selection[1])
534
+ }
535
+
536
+ is SelectionSyncOutcome.Refreshed -> {
537
+ refreshedUpdateJson = outcome.updateJson
538
+ textDocumentSelection(outcome.updateJson)
539
+ }
540
+
541
+ is SelectionSyncOutcome.Failed -> return null
542
+ } ?: return refreshedUpdateJson
543
+ publishCollaborationSelection(mapping[0], mapping[1])
544
+ return refreshedUpdateJson
545
+ }
546
+
547
+ override fun scalarPositionForDoc(docPos: Int): Int? =
548
+ mapPosition(backend.docToScalar(editorId, docPos), "scalar")
549
+
550
+ override fun docPositionForScalar(scalar: Int): Int? =
551
+ mapPosition(backend.scalarToDoc(editorId, scalar), "doc")
552
+
553
+ override fun insertText(text: String, atScalarPos: Int): String? {
554
+ if (text.isEmpty()) return currentStateJson()
555
+ if (nativeOwnerId != null) {
556
+ return performNativeIntent(
557
+ nativeIntent("insertText", atScalarPos, atScalarPos).put("text", text)
558
+ ).updateJsonOrNull()
559
+ }
560
+ val postCaret = atScalarPos + text.codePointCount(0, text.length)
561
+ return performMutation(
562
+ preSelection = intArrayOf(atScalarPos, atScalarPos),
563
+ postSelectionMirror = intArrayOf(postCaret, postCaret),
564
+ includeSelectionInUpdate = true
565
+ ) {
566
+ callWithEnvelope(JSONObject().put("text", text)) { requestJson ->
567
+ backend.applyInput(editorId, requestJson)
568
+ }
569
+ }
570
+ }
571
+
572
+ override fun replaceTextRange(scalarFrom: Int, scalarTo: Int, text: String): String? {
573
+ if (text.isEmpty()) {
574
+ return deleteScalarRange(scalarFrom, scalarTo)
575
+ }
576
+ if (nativeOwnerId != null) {
577
+ return performNativeIntent(
578
+ nativeIntent("replaceSelectionText", scalarFrom, scalarTo).put("text", text)
579
+ ).updateJsonOrNull()
580
+ }
581
+ val postCaret = scalarFrom + text.codePointCount(0, text.length)
582
+ // A range-replacing commit (autocorrect, paste-over-selection, IME
583
+ // commit over a composing range) is ONE typed ReplaceSelectionText
584
+ // transaction: the planner's InsertText is collapsed-only.
585
+ return performMutation(
586
+ preSelection = intArrayOf(scalarFrom, scalarTo),
587
+ postSelectionMirror = intArrayOf(postCaret, postCaret),
588
+ includeSelectionInUpdate = true
589
+ ) {
590
+ callWithEnvelope(
591
+ JSONObject().put(
592
+ "command",
593
+ JSONObject().put("type", "replaceSelectionText").put("text", text)
594
+ )
595
+ ) { requestJson ->
596
+ backend.applyCommand(editorId, requestJson)
597
+ }
598
+ }
599
+ }
600
+
601
+ override fun replaceTextRangeNative(
602
+ scalarFrom: Int,
603
+ scalarTo: Int,
604
+ text: String
605
+ ): EditorV2NativeIntentResult {
606
+ if (nativeOwnerId == null) return EditorV2NativeIntentResult.Rejected
607
+ if (text.isEmpty()) {
608
+ val clampedFrom = clampScalar(scalarFrom)
609
+ val clampedTo = clampScalar(scalarTo)
610
+ if (clampedFrom >= clampedTo) {
611
+ return refreshUnchangedNativeOutcome(
612
+ performNativeIntent(
613
+ nativeIntent("setSelection", clampedFrom, clampedFrom),
614
+ reportPositionEpochInvalid = true
615
+ )
616
+ )
617
+ }
618
+ return refreshUnchangedNativeOutcome(
619
+ performNativeIntent(
620
+ nativeIntent("deleteRange", clampedFrom, clampedTo),
621
+ reportPositionEpochInvalid = true
622
+ )
623
+ )
624
+ }
625
+ return refreshUnchangedNativeOutcome(
626
+ performNativeIntent(
627
+ nativeIntent("replaceSelectionText", scalarFrom, scalarTo).put("text", text),
628
+ reportPositionEpochInvalid = true
629
+ )
630
+ )
631
+ }
632
+
633
+ override fun deleteScalarRangeNative(
634
+ scalarFrom: Int,
635
+ scalarTo: Int
636
+ ): EditorV2NativeIntentResult {
637
+ if (nativeOwnerId == null) return EditorV2NativeIntentResult.Rejected
638
+ val clampedFrom = clampScalar(scalarFrom)
639
+ val clampedTo = clampScalar(scalarTo)
640
+ val intent = if (clampedFrom >= clampedTo) {
641
+ nativeIntent("setSelection", clampedFrom, clampedFrom)
642
+ } else {
643
+ nativeIntent("deleteRange", clampedFrom, clampedTo)
644
+ }
645
+ return refreshUnchangedNativeOutcome(
646
+ performNativeIntent(intent, reportPositionEpochInvalid = true)
647
+ )
648
+ }
649
+
650
+ override fun deleteScalarRange(scalarFrom: Int, scalarTo: Int): String? {
651
+ val clampedFrom = clampScalar(scalarFrom)
652
+ val clampedTo = clampScalar(scalarTo)
653
+ if (clampedFrom >= clampedTo) return currentStateJson()
654
+ if (nativeOwnerId != null) {
655
+ return deleteScalarRangeNative(clampedFrom, clampedTo).updateJsonOrNull()
656
+ }
657
+ return performMutation(
658
+ postSelectionMirror = intArrayOf(clampedFrom, clampedFrom),
659
+ includeSelectionInUpdate = true
660
+ ) {
661
+ callWithEnvelope(
662
+ JSONObject().put(
663
+ "command",
664
+ JSONObject()
665
+ .put("type", "deleteRange")
666
+ .put(
667
+ "range",
668
+ JSONObject()
669
+ .put("from", positionEnvelope(clampedFrom))
670
+ .put("to", positionEnvelope(clampedTo))
671
+ )
672
+ )
673
+ ) { requestJson ->
674
+ backend.applyCommand(editorId, requestJson)
675
+ }
676
+ }
677
+ }
678
+
679
+ override fun deleteBackwardAtSelection(anchor: Int, head: Int): String? {
680
+ if (nativeOwnerId != null) {
681
+ return performNativeIntent(
682
+ nativeIntent("deleteBackward", anchor, head)
683
+ ).updateJsonOrNull()
684
+ }
685
+ val postCaret = if (anchor == head) (anchor - 1).coerceAtLeast(0) else minOf(anchor, head)
686
+ return performMutation(
687
+ preSelection = intArrayOf(anchor, head),
688
+ postSelectionMirror = intArrayOf(postCaret, postCaret),
689
+ includeSelectionInUpdate = true
690
+ ) {
691
+ callWithEnvelope(
692
+ JSONObject().put("command", JSONObject().put("type", "deleteBackward"))
693
+ ) { requestJson ->
694
+ backend.applyCommand(editorId, requestJson)
695
+ }
696
+ }
697
+ }
698
+
699
+ override fun splitBlockAt(scalarPos: Int): EditorV2SplitRender? = if (nativeOwnerId != null) {
700
+ when (
701
+ val outcome = performNativeIntent(
702
+ nativeIntent("splitBlock", scalarPos, scalarPos)
703
+ )
704
+ ) {
705
+ is EditorV2NativeIntentResult.Applied ->
706
+ EditorV2SplitRender(outcome.render.updateJson, outcome.render.changed)
707
+
708
+ is EditorV2NativeIntentResult.Recovered ->
709
+ EditorV2SplitRender(outcome.updateJson, false)
710
+
711
+ EditorV2NativeIntentResult.Rejected -> null
712
+ }
713
+ } else {
714
+ performSplitMutation(
715
+ preSelection = intArrayOf(scalarPos, scalarPos),
716
+ postSelectionMirror = intArrayOf(scalarPos + 1, scalarPos + 1)
717
+ ) {
718
+ callWithEnvelope(
719
+ JSONObject().put("command", JSONObject().put("type", "splitBlock"))
720
+ ) { requestJson ->
721
+ backend.applyCommand(editorId, requestJson)
722
+ }
723
+ }
724
+ }
725
+
726
+ override fun deleteAndSplit(scalarFrom: Int, scalarTo: Int): EditorV2SplitRender? =
727
+ if (nativeOwnerId != null) {
728
+ when (
729
+ val outcome = performNativeIntent(
730
+ nativeIntent("deleteAndSplit", scalarFrom, scalarTo)
731
+ )
732
+ ) {
733
+ is EditorV2NativeIntentResult.Applied ->
734
+ EditorV2SplitRender(outcome.render.updateJson, outcome.render.changed)
735
+
736
+ is EditorV2NativeIntentResult.Recovered ->
737
+ EditorV2SplitRender(outcome.updateJson, false)
738
+
739
+ EditorV2NativeIntentResult.Rejected -> null
740
+ }
741
+ } else {
742
+ performSplitMutation(
743
+ preSelection = intArrayOf(scalarFrom, scalarTo),
744
+ postSelectionMirror = intArrayOf(scalarFrom + 1, scalarFrom + 1)
745
+ ) {
746
+ callWithEnvelope(
747
+ JSONObject().put("command", JSONObject().put("type", "deleteAndSplit"))
748
+ ) { requestJson ->
749
+ backend.applyCommand(editorId, requestJson)
750
+ }
751
+ }
752
+ }
753
+
754
+ override fun moveSelection(anchor: Int, head: Int, destination: Int): String? {
755
+ val from = minOf(anchor, head)
756
+ val to = maxOf(anchor, head)
757
+ return commandAtSelection(
758
+ JSONObject()
759
+ .put("type", "moveSelection")
760
+ .put(
761
+ "range",
762
+ JSONObject()
763
+ .put("from", positionEnvelope(from))
764
+ .put("to", positionEnvelope(to))
765
+ )
766
+ .put("at", positionEnvelope(destination)),
767
+ anchor,
768
+ head
769
+ )
770
+ }
771
+
772
+ override fun insertNode(nodeType: String, anchor: Int, head: Int): String? = commandAtSelection(
773
+ JSONObject().put("type", "insertNode").put("nodeType", nodeType),
774
+ anchor,
775
+ head
776
+ )
777
+
778
+ override fun insertContentHtmlAtSelection(html: String, anchor: Int, head: Int): String? =
779
+ commandAtSelection(
780
+ JSONObject().put("type", "insertContentHtml").put("html", html),
781
+ anchor,
782
+ head
783
+ )
784
+
785
+ override fun insertContentJsonAtSelection(json: String, anchor: Int, head: Int): String? {
786
+ val fragment = try {
787
+ JSONObject(json)
788
+ } catch (error: Exception) {
789
+ emit(contractError("insertContentJson fragment is not valid JSON"))
790
+ return null
791
+ }
792
+ return commandAtSelection(
793
+ JSONObject().put("type", "insertContentJson").put("json", fragment),
794
+ anchor,
795
+ head
796
+ )
797
+ }
798
+
799
+ override fun toggleMark(markName: String, anchor: Int, head: Int): String? = commandAtSelection(
800
+ JSONObject().put("type", "toggleMark").put("markType", markName),
801
+ anchor,
802
+ head
803
+ )
804
+
805
+ override fun setMark(markName: String, attrsJson: String, anchor: Int, head: Int): String? {
806
+ val attrs = try {
807
+ JSONObject(attrsJson)
808
+ } catch (error: Exception) {
809
+ emit(contractError("setMark attrs are not valid JSON"))
810
+ return null
811
+ }
812
+ return commandAtSelection(
813
+ JSONObject().put("type", "setMark").put("markType", markName).put("attrs", attrs),
814
+ anchor,
815
+ head
816
+ )
817
+ }
818
+
819
+ override fun unsetMark(markName: String, anchor: Int, head: Int): String? = commandAtSelection(
820
+ JSONObject().put("type", "unsetMark").put("markType", markName),
821
+ anchor,
822
+ head
823
+ )
824
+
825
+ override fun toggleHeading(level: Int, anchor: Int, head: Int): String? = commandAtSelection(
826
+ JSONObject().put("type", "toggleHeading").put("level", level),
827
+ anchor,
828
+ head
829
+ )
830
+
831
+ override fun toggleCodeBlock(anchor: Int, head: Int): String? =
832
+ commandAtSelection(JSONObject().put("type", "toggleCodeBlock"), anchor, head)
833
+
834
+ override fun toggleBlockquote(anchor: Int, head: Int): String? =
835
+ commandAtSelection(JSONObject().put("type", "toggleBlockquote"), anchor, head)
836
+
837
+ override fun wrapInList(listType: String, anchor: Int, head: Int): String? {
838
+ val itemType = EditorNodeTypes.listItemType(listType)
839
+ return commandAtSelection(
840
+ JSONObject().put(
841
+ "type",
842
+ "wrapInList"
843
+ ).put("listType", listType).put("itemType", itemType),
844
+ anchor,
845
+ head
846
+ )
847
+ }
848
+
849
+ override fun unwrapFromList(anchor: Int, head: Int): String? =
850
+ commandAtSelection(JSONObject().put("type", "unwrapFromList"), anchor, head)
851
+
852
+ override fun indentListItem(anchor: Int, head: Int): String? =
853
+ commandAtSelection(JSONObject().put("type", "indentListItem"), anchor, head)
854
+
855
+ override fun outdentListItem(anchor: Int, head: Int): String? =
856
+ commandAtSelection(JSONObject().put("type", "outdentListItem"), anchor, head)
857
+
858
+ override fun toggleTaskItemCheckedAtSelection(anchor: Int, head: Int): String? =
859
+ commandAtSelection(JSONObject().put("type", "toggleTaskItemChecked"), anchor, head)
860
+
861
+ override fun resizeImageAtDocPos(docPos: Int, width: Int, height: Int): String? {
862
+ val scalar = scalarPositionForDoc(docPos) ?: return null
863
+ return performMutation(adoptEngineSelection = true) {
864
+ callWithEnvelope(
865
+ JSONObject().put(
866
+ "command",
867
+ JSONObject()
868
+ .put("type", "resizeImage")
869
+ .put("at", positionEnvelope(scalar))
870
+ .put("width", width)
871
+ .put("height", height)
872
+ )
873
+ ) { requestJson ->
874
+ backend.applyCommand(editorId, requestJson)
875
+ }
876
+ }
877
+ }
878
+
879
+ override fun undo(): String? =
880
+ performHistoryMutation { requestJson -> backend.undo(editorId, requestJson) }
881
+
882
+ override fun redo(): String? =
883
+ performHistoryMutation { requestJson -> backend.redo(editorId, requestJson) }
884
+
885
+ override fun setContentHtml(html: String): String? =
886
+ performMutation(postSelectionMirror = intArrayOf(0, 0), includeSelectionInUpdate = true) {
887
+ callWithEnvelope(
888
+ JSONObject().put("setHtml", html).put("history", "resetAndClear")
889
+ ) { requestJson ->
890
+ backend.applyLocalApi(editorId, requestJson)
891
+ }
892
+ }
893
+
894
+ override fun setContentJson(json: String): String? {
895
+ val document = try {
896
+ JSONObject(json)
897
+ } catch (error: Exception) {
898
+ emit(contractError("setContentJson document is not valid JSON"))
899
+ return null
900
+ }
901
+ return performMutation(
902
+ postSelectionMirror = intArrayOf(0, 0),
903
+ includeSelectionInUpdate = true
904
+ ) {
905
+ callWithEnvelope(
906
+ JSONObject().put("setJson", document).put("history", "resetAndClear")
907
+ ) { requestJson ->
908
+ backend.applyLocalApi(editorId, requestJson)
909
+ }
910
+ }
911
+ }
912
+ }