@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.
- package/LICENSE +160 -0
- package/README.md +259 -0
- package/RUST-STANDARD-LIBRARY-NOTICES.html +8266 -0
- package/ReactNativeProseEditor.podspec +59 -0
- package/THIRD_PARTY_NOTICES.md +31155 -0
- package/android/build.gradle +188 -0
- package/android/consumer-rules.pro +18 -0
- package/android/expo/build.gradle +17 -0
- package/android/src/debug/java/com/apollohg/editor/viewer/PreparedProseDrawInstrumentation.kt +7 -0
- package/android/src/main/assets/editor-icons/MaterialIcons.json +2236 -0
- package/android/src/main/assets/editor-icons/MaterialIcons.ttf +0 -0
- package/android/src/main/java/com/apollohg/editor/AndroidApiCompat.kt +19 -0
- package/android/src/main/java/com/apollohg/editor/AndroidCollaborationTransport.kt +860 -0
- package/android/src/main/java/com/apollohg/editor/CaretGeometry.kt +91 -0
- package/android/src/main/java/com/apollohg/editor/CodeHighlighting.kt +141 -0
- package/android/src/main/java/com/apollohg/editor/DecodedBitmapBudget.kt +250 -0
- package/android/src/main/java/com/apollohg/editor/EditorAddons.kt +133 -0
- package/android/src/main/java/com/apollohg/editor/EditorBlockSpacing.kt +51 -0
- package/android/src/main/java/com/apollohg/editor/EditorBoxDrawable.kt +16 -0
- package/android/src/main/java/com/apollohg/editor/EditorBoxDrawing.kt +234 -0
- package/android/src/main/java/com/apollohg/editor/EditorCheckboxSpan.kt +87 -0
- package/android/src/main/java/com/apollohg/editor/EditorCodeHighlighting.kt +120 -0
- package/android/src/main/java/com/apollohg/editor/EditorDecorationLayer.java +18 -0
- package/android/src/main/java/com/apollohg/editor/EditorDocumentLayout.kt +626 -0
- package/android/src/main/java/com/apollohg/editor/EditorEditText.kt +1042 -0
- package/android/src/main/java/com/apollohg/editor/EditorEditTextAnnotations.kt +191 -0
- package/android/src/main/java/com/apollohg/editor/EditorEditTextCaret.kt +100 -0
- package/android/src/main/java/com/apollohg/editor/EditorEditTextClipboard.kt +101 -0
- package/android/src/main/java/com/apollohg/editor/EditorEditTextComposition.kt +220 -0
- package/android/src/main/java/com/apollohg/editor/EditorEditTextConfiguration.kt +316 -0
- package/android/src/main/java/com/apollohg/editor/EditorEditTextCorrection.kt +303 -0
- package/android/src/main/java/com/apollohg/editor/EditorEditTextDeferredUpdates.kt +327 -0
- package/android/src/main/java/com/apollohg/editor/EditorEditTextDeletion.kt +258 -0
- package/android/src/main/java/com/apollohg/editor/EditorEditTextDiagnostics.kt +83 -0
- package/android/src/main/java/com/apollohg/editor/EditorEditTextDragDrop.kt +67 -0
- package/android/src/main/java/com/apollohg/editor/EditorEditTextExternalComposition.kt +357 -0
- package/android/src/main/java/com/apollohg/editor/EditorEditTextHardwareInput.kt +277 -0
- package/android/src/main/java/com/apollohg/editor/EditorEditTextImages.kt +280 -0
- package/android/src/main/java/com/apollohg/editor/EditorEditTextInputLifecycle.kt +183 -0
- package/android/src/main/java/com/apollohg/editor/EditorEditTextInputPreparation.kt +79 -0
- package/android/src/main/java/com/apollohg/editor/EditorEditTextInputTraits.kt +384 -0
- package/android/src/main/java/com/apollohg/editor/EditorEditTextLayout.kt +100 -0
- package/android/src/main/java/com/apollohg/editor/EditorEditTextNativeMutation.kt +243 -0
- package/android/src/main/java/com/apollohg/editor/EditorEditTextPlaceholder.kt +154 -0
- package/android/src/main/java/com/apollohg/editor/EditorEditTextRenderPatch.kt +347 -0
- package/android/src/main/java/com/apollohg/editor/EditorEditTextRendering.kt +313 -0
- package/android/src/main/java/com/apollohg/editor/EditorEditTextRustCommands.kt +281 -0
- package/android/src/main/java/com/apollohg/editor/EditorEditTextSelection.kt +352 -0
- package/android/src/main/java/com/apollohg/editor/EditorEditTextState.kt +113 -0
- package/android/src/main/java/com/apollohg/editor/EditorEditTextTaskMarkers.kt +92 -0
- package/android/src/main/java/com/apollohg/editor/EditorEditTextTextCommit.kt +327 -0
- package/android/src/main/java/com/apollohg/editor/EditorEditTextToolbar.kt +84 -0
- package/android/src/main/java/com/apollohg/editor/EditorEditTextUpdates.kt +245 -0
- package/android/src/main/java/com/apollohg/editor/EditorGlyphHeightCursorDrawable.kt +42 -0
- package/android/src/main/java/com/apollohg/editor/EditorHeightBehavior.kt +13 -0
- package/android/src/main/java/com/apollohg/editor/EditorInputConnection.kt +923 -0
- package/android/src/main/java/com/apollohg/editor/EditorInputCoordinates.kt +191 -0
- package/android/src/main/java/com/apollohg/editor/EditorInputCorrection.kt +107 -0
- package/android/src/main/java/com/apollohg/editor/EditorInputCursorGeometry.kt +128 -0
- package/android/src/main/java/com/apollohg/editor/EditorInputSnapshots.kt +134 -0
- package/android/src/main/java/com/apollohg/editor/EditorInputSurroundingDeletion.kt +321 -0
- package/android/src/main/java/com/apollohg/editor/EditorKeyboardToolbarView.kt +851 -0
- package/android/src/main/java/com/apollohg/editor/EditorMentionStyle.kt +192 -0
- package/android/src/main/java/com/apollohg/editor/EditorReconciliationWatcher.kt +46 -0
- package/android/src/main/java/com/apollohg/editor/EditorStyleSheet.kt +303 -0
- package/android/src/main/java/com/apollohg/editor/EditorStyleSheetSpans.kt +253 -0
- package/android/src/main/java/com/apollohg/editor/EditorSurfaceInputConnection.kt +67 -0
- package/android/src/main/java/com/apollohg/editor/EditorTextDecorationDrawing.kt +143 -0
- package/android/src/main/java/com/apollohg/editor/EditorTextSurface.kt +712 -0
- package/android/src/main/java/com/apollohg/editor/EditorTextSurfaceDragDrop.kt +94 -0
- package/android/src/main/java/com/apollohg/editor/EditorTextSurfaceInteraction.kt +708 -0
- package/android/src/main/java/com/apollohg/editor/EditorTheme.kt +650 -0
- package/android/src/main/java/com/apollohg/editor/EditorV2Adapter.kt +912 -0
- package/android/src/main/java/com/apollohg/editor/EditorV2AdapterMutations.kt +402 -0
- package/android/src/main/java/com/apollohg/editor/EditorV2AdapterRendering.kt +123 -0
- package/android/src/main/java/com/apollohg/editor/EditorV2AdapterSelection.kt +203 -0
- package/android/src/main/java/com/apollohg/editor/EditorV2Backend.kt +120 -0
- package/android/src/main/java/com/apollohg/editor/EditorV2Driver.kt +87 -0
- package/android/src/main/java/com/apollohg/editor/EditorV2Registry.kt +97 -0
- package/android/src/main/java/com/apollohg/editor/EditorV2RenderValidation.kt +409 -0
- package/android/src/main/java/com/apollohg/editor/ExpoAutoGrowStyleSizePublisher.kt +34 -0
- package/android/src/main/java/com/apollohg/editor/ImageResizeOverlayView.kt +266 -0
- package/android/src/main/java/com/apollohg/editor/ImeTextCoordinateMapper.kt +102 -0
- package/android/src/main/java/com/apollohg/editor/KeyboardToolbarImeAnimationController.kt +101 -0
- package/android/src/main/java/com/apollohg/editor/MentionSuggestionChipView.kt +234 -0
- package/android/src/main/java/com/apollohg/editor/NativeCollaborationTransportRegistry.kt +493 -0
- package/android/src/main/java/com/apollohg/editor/NativeEditorExpoView.kt +813 -0
- package/android/src/main/java/com/apollohg/editor/NativeEditorExpoViewAtoms.kt +68 -0
- package/android/src/main/java/com/apollohg/editor/NativeEditorExpoViewBinding.kt +126 -0
- package/android/src/main/java/com/apollohg/editor/NativeEditorExpoViewDiagnostics.kt +208 -0
- package/android/src/main/java/com/apollohg/editor/NativeEditorExpoViewErrors.kt +146 -0
- package/android/src/main/java/com/apollohg/editor/NativeEditorExpoViewEvents.kt +150 -0
- package/android/src/main/java/com/apollohg/editor/NativeEditorExpoViewExternalComposition.kt +39 -0
- package/android/src/main/java/com/apollohg/editor/NativeEditorExpoViewFocus.kt +176 -0
- package/android/src/main/java/com/apollohg/editor/NativeEditorExpoViewLifecycle.kt +302 -0
- package/android/src/main/java/com/apollohg/editor/NativeEditorExpoViewMentions.kt +259 -0
- package/android/src/main/java/com/apollohg/editor/NativeEditorExpoViewNativeActions.kt +179 -0
- package/android/src/main/java/com/apollohg/editor/NativeEditorExpoViewOutsideTap.kt +214 -0
- package/android/src/main/java/com/apollohg/editor/NativeEditorExpoViewPendingUpdates.kt +376 -0
- package/android/src/main/java/com/apollohg/editor/NativeEditorExpoViewProperties.kt +234 -0
- package/android/src/main/java/com/apollohg/editor/NativeEditorExpoViewPropertyRetries.kt +197 -0
- package/android/src/main/java/com/apollohg/editor/NativeEditorExpoViewToolbar.kt +285 -0
- package/android/src/main/java/com/apollohg/editor/NativeEditorExpoViewTypes.kt +28 -0
- package/android/src/main/java/com/apollohg/editor/NativeEditorExpoViewUpdates.kt +271 -0
- package/android/src/main/java/com/apollohg/editor/NativeEditorModule.kt +687 -0
- package/android/src/main/java/com/apollohg/editor/NativeEditorOutsideTapDispatcher.kt +380 -0
- package/android/src/main/java/com/apollohg/editor/NativeEditorV2Numbers.kt +45 -0
- package/android/src/main/java/com/apollohg/editor/NativeEditorViewRegistry.kt +372 -0
- package/android/src/main/java/com/apollohg/editor/NativeImagePipeline.kt +22 -0
- package/android/src/main/java/com/apollohg/editor/NativeToolbar.kt +193 -0
- package/android/src/main/java/com/apollohg/editor/NativeToolbarIcons.kt +177 -0
- package/android/src/main/java/com/apollohg/editor/NativeToolbarItem.kt +274 -0
- package/android/src/main/java/com/apollohg/editor/OkHttpCollaborationSocket.kt +102 -0
- package/android/src/main/java/com/apollohg/editor/OrderedListMarkerFormatter.kt +130 -0
- package/android/src/main/java/com/apollohg/editor/PointerTransparentView.java +18 -0
- package/android/src/main/java/com/apollohg/editor/PositionBridge.kt +128 -0
- package/android/src/main/java/com/apollohg/editor/ProseViewerView.kt +854 -0
- package/android/src/main/java/com/apollohg/editor/RemoteSelectionOverlayView.kt +314 -0
- package/android/src/main/java/com/apollohg/editor/RenderBlockSpans.kt +314 -0
- package/android/src/main/java/com/apollohg/editor/RenderBridge.kt +224 -0
- package/android/src/main/java/com/apollohg/editor/RenderBridgeBlockStyles.kt +407 -0
- package/android/src/main/java/com/apollohg/editor/RenderBridgeElements.kt +544 -0
- package/android/src/main/java/com/apollohg/editor/RenderBridgeInlineAndAtoms.kt +631 -0
- package/android/src/main/java/com/apollohg/editor/RenderBridgeParagraphs.kt +215 -0
- package/android/src/main/java/com/apollohg/editor/RenderImageDecoder.kt +748 -0
- package/android/src/main/java/com/apollohg/editor/RenderImageLoader.kt +900 -0
- package/android/src/main/java/com/apollohg/editor/RenderLayoutConstants.kt +117 -0
- package/android/src/main/java/com/apollohg/editor/RenderMediaSpans.kt +337 -0
- package/android/src/main/java/com/apollohg/editor/RenderParagraphSpans.kt +182 -0
- package/android/src/main/java/com/apollohg/editor/RichTextEditorView.kt +951 -0
- package/android/src/main/java/com/apollohg/editor/SharedNativeImagePipeline.kt +78 -0
- package/android/src/main/java/com/apollohg/editor/UniffiEditorV2Backend.kt +261 -0
- package/android/src/main/java/com/apollohg/editor/viewer/AndroidProseLayoutEngine.kt +1656 -0
- package/android/src/main/java/com/apollohg/editor/viewer/FabricAttachmentSidecars.kt +80 -0
- package/android/src/main/java/com/apollohg/editor/viewer/FabricLeaseHandleBridge.kt +59 -0
- package/android/src/main/java/com/apollohg/editor/viewer/FallbackSelectionGeometry.kt +450 -0
- package/android/src/main/java/com/apollohg/editor/viewer/PreparedProseDrawingView.kt +678 -0
- package/android/src/main/java/com/apollohg/editor/viewer/PreparedProseInstrumentation.kt +608 -0
- package/android/src/main/java/com/apollohg/editor/viewer/PreparedProseLayout.kt +186 -0
- package/android/src/main/java/com/apollohg/editor/viewer/PreparedProseLayoutCache.kt +393 -0
- package/android/src/main/java/com/apollohg/editor/viewer/PreparedProseLayoutRegistry.kt +828 -0
- package/android/src/main/java/com/apollohg/editor/viewer/PreparedProseTheme.kt +316 -0
- package/android/src/main/java/com/apollohg/editor/viewer/PreparedProseViewerManager.kt +900 -0
- package/android/src/main/java/com/apollohg/editor/viewer/PreparedProseViewerPackage.kt +16 -0
- package/android/src/main/java/com/apollohg/editor/viewer/PreparedViewerAtoms.kt +89 -0
- package/android/src/main/java/com/apollohg/editor/viewer/ViewerCodeHighlighting.kt +91 -0
- package/android/src/main/java/com/apollohg/editor/viewer/ViewerDocument.kt +453 -0
- package/android/src/main/java/com/apollohg/editor/viewer/ViewerFontEnvironment.kt +282 -0
- package/android/src/main/java/com/apollohg/editor/viewer/ViewerImagePipeline.kt +460 -0
- package/android/src/main/jni/CMakeLists.txt +85 -0
- package/android/src/main/jni/PreparedProseViewerMeasurementsManager.cpp +334 -0
- package/android/src/main/jni/ReactNativeProseEditorSpec.h +17 -0
- package/android/src/main/jni/reactnativeproseeditor.h +6 -0
- package/android/src/main/res/values/attrs.xml +6 -0
- package/android/src/release/java/com/apollohg/editor/viewer/PreparedProseDrawInstrumentation.kt +9 -0
- package/app.plugin.js +62 -0
- package/common/cpp/react/renderer/components/PreparedProseViewer/PreparedProseMeasurementsManager.h +62 -0
- package/common/cpp/react/renderer/components/PreparedProseViewer/PreparedProseViewerComponentDescriptor.h +30 -0
- package/common/cpp/react/renderer/components/PreparedProseViewer/PreparedProseViewerShadowNode.cpp +192 -0
- package/common/cpp/react/renderer/components/PreparedProseViewer/PreparedProseViewerShadowNode.h +46 -0
- package/common/cpp/react/renderer/components/PreparedProseViewer/PreparedProseViewerState.h +145 -0
- package/dist/AtomHost.d.ts +17 -0
- package/dist/AtomHost.js +135 -0
- package/dist/DefaultAtomChip.d.ts +2 -0
- package/dist/DefaultAtomChip.js +22 -0
- package/dist/EditorAddon.d.ts +32 -0
- package/dist/EditorAddon.js +29 -0
- package/dist/EditorAddonNormalization.d.ts +6 -0
- package/dist/EditorAddonNormalization.js +48 -0
- package/dist/EditorMentionThemeNormalization.d.ts +8 -0
- package/dist/EditorMentionThemeNormalization.js +22 -0
- package/dist/EditorMentionThemeValidation.d.ts +12 -0
- package/dist/EditorMentionThemeValidation.js +95 -0
- package/dist/EditorStyleSheet.d.ts +4 -0
- package/dist/EditorStyleSheet.js +10 -0
- package/dist/EditorStyleSheetNormalization.d.ts +3 -0
- package/dist/EditorStyleSheetNormalization.js +226 -0
- package/dist/EditorStyleSheetTypes.d.ts +151 -0
- package/dist/EditorStyleSheetTypes.js +2 -0
- package/dist/EditorTheme.d.ts +117 -0
- package/dist/EditorTheme.js +41 -0
- package/dist/EditorToolbar.d.ts +4 -0
- package/dist/EditorToolbar.js +17 -0
- package/dist/EditorToolbarComponent.d.ts +13 -0
- package/dist/EditorToolbarComponent.js +24 -0
- package/dist/EditorToolbarItems.d.ts +9 -0
- package/dist/EditorToolbarItems.js +58 -0
- package/dist/EditorToolbarRegistry.d.ts +59 -0
- package/dist/EditorToolbarRegistry.js +175 -0
- package/dist/EditorToolbarTypes.d.ts +273 -0
- package/dist/EditorToolbarTypes.js +2 -0
- package/dist/EditorToolbarVisuals.d.ts +154 -0
- package/dist/EditorToolbarVisuals.js +228 -0
- package/dist/EditorUpdateRevision.d.ts +8 -0
- package/dist/EditorUpdateRevision.js +22 -0
- package/dist/ExternalTextComposition.d.ts +45 -0
- package/dist/ExternalTextComposition.js +537 -0
- package/dist/ImageLoadingPolicy.d.ts +54 -0
- package/dist/ImageLoadingPolicy.js +60 -0
- package/dist/NativeEditorBoundaryError.d.ts +111 -0
- package/dist/NativeEditorBoundaryError.js +268 -0
- package/dist/NativeEditorBridge.d.ts +9 -0
- package/dist/NativeEditorBridge.js +37 -0
- package/dist/NativeEditorCollaborationTransport.d.ts +154 -0
- package/dist/NativeEditorCollaborationTransport.js +275 -0
- package/dist/NativeEditorCreateConfig.d.ts +16 -0
- package/dist/NativeEditorCreateConfig.js +249 -0
- package/dist/NativeEditorCreateJson.d.ts +76 -0
- package/dist/NativeEditorCreateJson.js +474 -0
- package/dist/NativeEditorCreateValidation.d.ts +32 -0
- package/dist/NativeEditorCreateValidation.js +150 -0
- package/dist/NativeEditorDocumentBridge.d.ts +72 -0
- package/dist/NativeEditorDocumentBridge.js +305 -0
- package/dist/NativeEditorDocumentHandle.d.ts +70 -0
- package/dist/NativeEditorDocumentHandle.js +89 -0
- package/dist/NativeEditorLocalAwareness.d.ts +34 -0
- package/dist/NativeEditorLocalAwareness.js +153 -0
- package/dist/NativeEditorNativeModule.d.ts +48 -0
- package/dist/NativeEditorNativeModule.js +34 -0
- package/dist/NativeEditorRenderNormalization.d.ts +22 -0
- package/dist/NativeEditorRenderNormalization.js +274 -0
- package/dist/NativeEditorResultNormalization.d.ts +108 -0
- package/dist/NativeEditorResultNormalization.js +400 -0
- package/dist/NativeEditorTypes.d.ts +318 -0
- package/dist/NativeEditorTypes.js +15 -0
- package/dist/NativeEditorV2Decimal.d.ts +5 -0
- package/dist/NativeEditorV2Decimal.js +18 -0
- package/dist/NativeProseViewer.d.ts +122 -0
- package/dist/NativeProseViewer.js +130 -0
- package/dist/NativeRichTextEditor.d.ts +3 -0
- package/dist/NativeRichTextEditor.js +6 -0
- package/dist/ResourceLimits.d.ts +100 -0
- package/dist/ResourceLimits.js +80 -0
- package/dist/RichTextEditor.d.ts +4 -0
- package/dist/RichTextEditor.js +25 -0
- package/dist/RichTextEditorNativeTypes.d.ts +122 -0
- package/dist/RichTextEditorNativeTypes.js +2 -0
- package/dist/RichTextEditorNativeView.d.ts +12 -0
- package/dist/RichTextEditorNativeView.js +15 -0
- package/dist/RichTextEditorSerialization.d.ts +53 -0
- package/dist/RichTextEditorSerialization.js +283 -0
- package/dist/RichTextEditorTypes.d.ts +281 -0
- package/dist/RichTextEditorTypes.js +2 -0
- package/dist/ViewerConfiguration.d.ts +22 -0
- package/dist/ViewerConfiguration.js +6 -0
- package/dist/YjsCollaboration.d.ts +146 -0
- package/dist/YjsCollaboration.js +496 -0
- package/dist/addons.d.ts +193 -0
- package/dist/addons.js +122 -0
- package/dist/atomConstants.d.ts +3 -0
- package/dist/atomConstants.js +6 -0
- package/dist/atomInstances.d.ts +35 -0
- package/dist/atomInstances.js +79 -0
- package/dist/atomPolicy.d.ts +4 -0
- package/dist/atomPolicy.js +47 -0
- package/dist/atomUpdates.d.ts +2 -0
- package/dist/atomUpdates.js +38 -0
- package/dist/atoms.d.ts +92 -0
- package/dist/atoms.js +222 -0
- package/dist/attributeValidation.d.ts +4 -0
- package/dist/attributeValidation.js +97 -0
- package/dist/contentExpression.d.ts +6 -0
- package/dist/contentExpression.js +335 -0
- package/dist/index.d.ts +21 -0
- package/dist/index.js +78 -0
- package/dist/listMarkers.d.ts +15 -0
- package/dist/listMarkers.js +21 -0
- package/dist/schemaDefinition.d.ts +143 -0
- package/dist/schemaDefinition.js +206 -0
- package/dist/schemaDocument.d.ts +17 -0
- package/dist/schemaDocument.js +69 -0
- package/dist/schemaDocumentConstruction.d.ts +5 -0
- package/dist/schemaDocumentConstruction.js +125 -0
- package/dist/schemaNormalization.d.ts +29 -0
- package/dist/schemaNormalization.js +313 -0
- package/dist/schemaPresets.d.ts +68 -0
- package/dist/schemaPresets.js +198 -0
- package/dist/schemaResolution.d.ts +9 -0
- package/dist/schemaResolution.js +211 -0
- package/dist/schemas.d.ts +5 -0
- package/dist/schemas.js +28 -0
- package/dist/specs/PreparedProseViewerNativeComponent.d.ts +37 -0
- package/dist/specs/PreparedProseViewerNativeComponent.js +6 -0
- package/dist/useEditorToolbarInteractions.d.ts +12 -0
- package/dist/useEditorToolbarInteractions.js +218 -0
- package/dist/useEditorToolbarItems.d.ts +8 -0
- package/dist/useEditorToolbarItems.js +280 -0
- package/dist/useEditorToolbarPresentation.d.ts +4 -0
- package/dist/useEditorToolbarPresentation.js +203 -0
- package/dist/useEditorToolbarState.d.ts +63 -0
- package/dist/useEditorToolbarState.js +108 -0
- package/dist/useFocusPreservingFrames.d.ts +17 -0
- package/dist/useFocusPreservingFrames.js +108 -0
- package/dist/useNativeEditor.d.ts +66 -0
- package/dist/useNativeEditor.js +370 -0
- package/dist/useRichTextEditorCommands.d.ts +21 -0
- package/dist/useRichTextEditorCommands.js +299 -0
- package/dist/useRichTextEditorEvents.d.ts +18 -0
- package/dist/useRichTextEditorEvents.js +216 -0
- package/dist/useRichTextEditorMentions.d.ts +11 -0
- package/dist/useRichTextEditorMentions.js +316 -0
- package/dist/useRichTextEditorPresentation.d.ts +5 -0
- package/dist/useRichTextEditorPresentation.js +178 -0
- package/dist/useRichTextEditorState.d.ts +180 -0
- package/dist/useRichTextEditorState.js +405 -0
- package/dist/useRichTextEditorUpdates.d.ts +10 -0
- package/dist/useRichTextEditorUpdates.js +308 -0
- package/dist/useViewerAtoms.d.ts +38 -0
- package/dist/useViewerAtoms.js +288 -0
- package/expo-module.config.json +13 -0
- package/ios/EditorAddons.swift +354 -0
- package/ios/EditorCodeHighlighting.swift +184 -0
- package/ios/EditorCore.xcframework/Info.plist +44 -0
- package/ios/EditorCore.xcframework/ios-arm64/libeditor_core.a +0 -0
- package/ios/EditorCore.xcframework/ios-arm64_x86_64-simulator/libeditor_core.a +0 -0
- package/ios/EditorInteractionOverlays.swift +697 -0
- package/ios/EditorLayoutManager.swift +971 -0
- package/ios/EditorNodeTypes.swift +37 -0
- package/ios/EditorStyleSheet.swift +461 -0
- package/ios/EditorTextView+AttributedPatch.swift +305 -0
- package/ios/EditorTextView+Binding.swift +61 -0
- package/ios/EditorTextView+Caret.swift +333 -0
- package/ios/EditorTextView+Commands.swift +203 -0
- package/ios/EditorTextView+Delegate.swift +65 -0
- package/ios/EditorTextView+Diagnostics.swift +225 -0
- package/ios/EditorTextView+DragDrop.swift +290 -0
- package/ios/EditorTextView+ExternalComposition.swift +364 -0
- package/ios/EditorTextView+Images.swift +354 -0
- package/ios/EditorTextView+InputTraits.swift +200 -0
- package/ios/EditorTextView+KeyboardInput.swift +318 -0
- package/ios/EditorTextView+Layout.swift +245 -0
- package/ios/EditorTextView+MarkedText.swift +267 -0
- package/ios/EditorTextView+NativeInputLifecycle.swift +372 -0
- package/ios/EditorTextView+NativeMutation.swift +471 -0
- package/ios/EditorTextView+Reconciliation.swift +97 -0
- package/ios/EditorTextView+RenderPatch.swift +573 -0
- package/ios/EditorTextView+Rendering.swift +539 -0
- package/ios/EditorTextView+Selection.swift +542 -0
- package/ios/EditorTextView.swift +953 -0
- package/ios/EditorTheme.swift +626 -0
- package/ios/EditorV2Adapter+Commands.swift +204 -0
- package/ios/EditorV2Adapter+Envelope.swift +238 -0
- package/ios/EditorV2Adapter+Mutation.swift +392 -0
- package/ios/EditorV2Adapter+Registry.swift +185 -0
- package/ios/EditorV2Adapter+RenderState.swift +360 -0
- package/ios/EditorV2Adapter+RenderValidation.swift +420 -0
- package/ios/EditorV2Adapter+Selection.swift +329 -0
- package/ios/EditorV2Adapter+TextCommands.swift +430 -0
- package/ios/EditorV2Adapter.swift +376 -0
- package/ios/EditorV2Shadow.swift +353 -0
- package/ios/Generated_editor_core.swift +2378 -0
- package/ios/NativeCodeHighlighting.swift +159 -0
- package/ios/NativeCollaborationSocket.swift +144 -0
- package/ios/NativeCollaborationTransport+Protocol.swift +258 -0
- package/ios/NativeCollaborationTransport+Socket.swift +379 -0
- package/ios/NativeCollaborationTransport+Validation.swift +103 -0
- package/ios/NativeCollaborationTransport.swift +322 -0
- package/ios/NativeCollaborationTransportRegistry.swift +521 -0
- package/ios/NativeEditorExpoView+AccessoryRetry.swift +219 -0
- package/ios/NativeEditorExpoView+Binding.swift +268 -0
- package/ios/NativeEditorExpoView+Diagnostics.swift +66 -0
- package/ios/NativeEditorExpoView+Events.swift +131 -0
- package/ios/NativeEditorExpoView+Focus.swift +169 -0
- package/ios/NativeEditorExpoView+MentionRetry.swift +288 -0
- package/ios/NativeEditorExpoView+Mentions.swift +288 -0
- package/ios/NativeEditorExpoView+Properties.swift +300 -0
- package/ios/NativeEditorExpoView+Toolbar.swift +86 -0
- package/ios/NativeEditorExpoView+Updates.swift +312 -0
- package/ios/NativeEditorExpoView.swift +349 -0
- package/ios/NativeEditorModule.swift +856 -0
- package/ios/NativeEditorViewRegistry.swift +226 -0
- package/ios/NativeToolbar+ButtonStyle.swift +214 -0
- package/ios/NativeToolbar+Buttons.swift +228 -0
- package/ios/NativeToolbar+Diagnostics.swift +114 -0
- package/ios/NativeToolbar+Menu.swift +101 -0
- package/ios/NativeToolbar+Models.swift +519 -0
- package/ios/NativeToolbar+Placeholder.swift +39 -0
- package/ios/NativeToolbar.swift +612 -0
- package/ios/OrderedListMarkerFormatter.swift +103 -0
- package/ios/PositionBridge.swift +596 -0
- package/ios/ProseViewerView.swift +462 -0
- package/ios/RenderBridge+Atoms.swift +288 -0
- package/ios/RenderBridge+Attachments.swift +246 -0
- package/ios/RenderBridge+BlockBoundaries.swift +313 -0
- package/ios/RenderBridge+Style.swift +343 -0
- package/ios/RenderBridge.swift +704 -0
- package/ios/RichTextEditorView.swift +930 -0
- package/ios/SharedNativeImagePipeline+Cache.swift +189 -0
- package/ios/SharedNativeImagePipeline+Transport.swift +328 -0
- package/ios/SharedNativeImagePipeline.swift +533 -0
- package/ios/Viewer/CoreTextProseLayoutEngine+AttributedText.swift +436 -0
- package/ios/Viewer/CoreTextProseLayoutEngine+Models.swift +322 -0
- package/ios/Viewer/CoreTextProseLayoutEngine.swift +635 -0
- package/ios/Viewer/Fabric/PREPPreparedProseViewerComponentView.h +4 -0
- package/ios/Viewer/Fabric/PREPPreparedProseViewerComponentView.mm +767 -0
- package/ios/Viewer/Fabric/PreparedProseMeasurementsManager.mm +118 -0
- package/ios/Viewer/NativeSVGImageDecoder.h +9 -0
- package/ios/Viewer/NativeSVGImageDecoder.mm +106 -0
- package/ios/Viewer/NativeSVGPreflight.h +11 -0
- package/ios/Viewer/NativeSVGPreflight.mm +219 -0
- package/ios/Viewer/PreparedProseDrawingView.swift +639 -0
- package/ios/Viewer/PreparedProseInstrumentation.swift +387 -0
- package/ios/Viewer/PreparedProseLayout.swift +326 -0
- package/ios/Viewer/PreparedProseLayoutCache.swift +766 -0
- package/ios/Viewer/PreparedProseLayoutRegistry+Artifacts.swift +377 -0
- package/ios/Viewer/PreparedProseLayoutRegistry+Fabric.swift +582 -0
- package/ios/Viewer/PreparedProseLayoutRegistry+FabricOwnership.swift +128 -0
- package/ios/Viewer/PreparedProseLayoutRegistry.swift +381 -0
- package/ios/Viewer/ViewerDocument.swift +575 -0
- package/ios/Viewer/ViewerFontEnvironment.swift +283 -0
- package/ios/Viewer/ViewerImagePipeline.swift +478 -0
- package/ios/editor_coreFFI/editor_coreFFI.h +1023 -0
- package/ios/editor_coreFFI/module.modulemap +7 -0
- package/package.json +151 -0
- package/react-native.config.js +17 -0
- package/rust/android/arm64-v8a/libeditor_core.so +0 -0
- package/rust/android/armeabi-v7a/libeditor_core.so +0 -0
- package/rust/android/x86/libeditor_core.so +0 -0
- package/rust/android/x86_64/libeditor_core.so +0 -0
- package/rust/bindings/kotlin/uniffi/editor_core/editor_core.kt +3146 -0
- package/src/AtomHost.tsx +180 -0
- package/src/DefaultAtomChip.tsx +27 -0
- package/src/EditorAddon.ts +65 -0
- package/src/EditorAddonNormalization.ts +49 -0
- package/src/EditorMentionThemeNormalization.ts +25 -0
- package/src/EditorMentionThemeValidation.ts +133 -0
- package/src/EditorStyleSheet.ts +9 -0
- package/src/EditorStyleSheetNormalization.ts +219 -0
- package/src/EditorStyleSheetTypes.ts +189 -0
- package/src/EditorTheme.ts +196 -0
- package/src/EditorToolbar.tsx +31 -0
- package/src/EditorToolbarComponent.tsx +23 -0
- package/src/EditorToolbarItems.tsx +64 -0
- package/src/EditorToolbarRegistry.tsx +254 -0
- package/src/EditorToolbarTypes.tsx +322 -0
- package/src/EditorToolbarVisuals.tsx +270 -0
- package/src/EditorUpdateRevision.ts +26 -0
- package/src/ExternalTextComposition.ts +658 -0
- package/src/ImageLoadingPolicy.ts +125 -0
- package/src/NativeEditorBoundaryError.ts +345 -0
- package/src/NativeEditorBridge.ts +93 -0
- package/src/NativeEditorCollaborationTransport.ts +493 -0
- package/src/NativeEditorCreateConfig.ts +326 -0
- package/src/NativeEditorCreateJson.ts +579 -0
- package/src/NativeEditorCreateValidation.ts +178 -0
- package/src/NativeEditorDocumentBridge.ts +485 -0
- package/src/NativeEditorDocumentHandle.ts +168 -0
- package/src/NativeEditorLocalAwareness.ts +168 -0
- package/src/NativeEditorNativeModule.ts +97 -0
- package/src/NativeEditorRenderNormalization.ts +320 -0
- package/src/NativeEditorResultNormalization.ts +469 -0
- package/src/NativeEditorTypes.ts +366 -0
- package/src/NativeEditorV2Decimal.ts +13 -0
- package/src/NativeProseViewer.tsx +356 -0
- package/src/NativeRichTextEditor.tsx +33 -0
- package/src/ResourceLimits.ts +187 -0
- package/src/RichTextEditor.tsx +27 -0
- package/src/RichTextEditorNativeTypes.tsx +144 -0
- package/src/RichTextEditorNativeView.tsx +21 -0
- package/src/RichTextEditorSerialization.tsx +381 -0
- package/src/RichTextEditorTypes.tsx +327 -0
- package/src/ViewerConfiguration.ts +23 -0
- package/src/YjsCollaboration.ts +692 -0
- package/src/addons.ts +311 -0
- package/src/atomConstants.ts +3 -0
- package/src/atomInstances.ts +123 -0
- package/src/atomPolicy.ts +47 -0
- package/src/atomUpdates.ts +52 -0
- package/src/atoms.ts +379 -0
- package/src/attributeValidation.ts +116 -0
- package/src/contentExpression.ts +338 -0
- package/src/index.ts +295 -0
- package/src/listMarkers.ts +18 -0
- package/src/schemaDefinition.ts +395 -0
- package/src/schemaDocument.ts +92 -0
- package/src/schemaDocumentConstruction.ts +148 -0
- package/src/schemaNormalization.ts +367 -0
- package/src/schemaPresets.ts +250 -0
- package/src/schemaResolution.ts +242 -0
- package/src/schemas.ts +43 -0
- package/src/specs/PreparedProseViewerNativeComponent.ts +40 -0
- package/src/useEditorToolbarInteractions.tsx +329 -0
- package/src/useEditorToolbarItems.tsx +390 -0
- package/src/useEditorToolbarPresentation.tsx +483 -0
- package/src/useEditorToolbarState.tsx +172 -0
- package/src/useFocusPreservingFrames.ts +171 -0
- package/src/useNativeEditor.ts +534 -0
- package/src/useRichTextEditorCommands.tsx +478 -0
- package/src/useRichTextEditorEvents.tsx +342 -0
- package/src/useRichTextEditorMentions.tsx +441 -0
- package/src/useRichTextEditorPresentation.tsx +563 -0
- package/src/useRichTextEditorState.tsx +620 -0
- package/src/useRichTextEditorUpdates.tsx +403 -0
- package/src/useViewerAtoms.tsx +427 -0
|
@@ -0,0 +1,471 @@
|
|
|
1
|
+
import os
|
|
2
|
+
import UIKit
|
|
3
|
+
|
|
4
|
+
extension EditorTextView {
|
|
5
|
+
struct NativeTextMutation {
|
|
6
|
+
let from: UInt32
|
|
7
|
+
let to: UInt32
|
|
8
|
+
/// The replaced span as UTF-16 in the authorized storage. Kept so a
|
|
9
|
+
/// caret can be converted against that storage patched with this
|
|
10
|
+
/// replacement, which is the only ruler that still carries the
|
|
11
|
+
/// document's structural attributes.
|
|
12
|
+
let authorizedReplacementUtf16Range: NSRange
|
|
13
|
+
let replacementText: String
|
|
14
|
+
let resultingText: String
|
|
15
|
+
let authorizedText: String
|
|
16
|
+
let selectionAnchor: UInt32?
|
|
17
|
+
let selectionHead: UInt32?
|
|
18
|
+
let authorizedSelectionUtf16Range: NSRange?
|
|
19
|
+
let rawSelectionUtf16Range: NSRange?
|
|
20
|
+
let acceptedSpaceCaretUtf16Offset: Int?
|
|
21
|
+
let selectionRevision: UInt64
|
|
22
|
+
let capturedWhileFirstResponder: Bool
|
|
23
|
+
let capturedWhileEditable: Bool
|
|
24
|
+
let capturedAfterBlur: Bool
|
|
25
|
+
let inputGeneration: UInt64
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
/// The last Rust-authorized storage with one native replacement applied.
|
|
29
|
+
///
|
|
30
|
+
/// A caret inside a natively mutated document cannot be converted against
|
|
31
|
+
/// the live text view. A keyboard correction replaces the word with an
|
|
32
|
+
/// unattributed string, which strips the structural attributes the
|
|
33
|
+
/// utf16→scalar conversion reads to count a list's block openings, so the
|
|
34
|
+
/// live view maps the caret as though the line were never wrapped. The
|
|
35
|
+
/// authorized storage still carries those attributes; patching its text
|
|
36
|
+
/// with the same replacement gives a ruler that matches the new text
|
|
37
|
+
/// while keeping the structure. Falls back to the unpatched storage when
|
|
38
|
+
/// the range no longer addresses it.
|
|
39
|
+
private func authorizedStorageApplying(
|
|
40
|
+
_ replacementText: String,
|
|
41
|
+
inUtf16Range range: NSRange
|
|
42
|
+
) -> NSAttributedString {
|
|
43
|
+
guard range.location >= 0,
|
|
44
|
+
range.length >= 0,
|
|
45
|
+
NSMaxRange(range) <= lastAuthorizedAttributedTextStorage.length
|
|
46
|
+
else {
|
|
47
|
+
return lastAuthorizedAttributedTextStorage
|
|
48
|
+
}
|
|
49
|
+
let patched = NSMutableAttributedString(
|
|
50
|
+
attributedString: lastAuthorizedAttributedTextStorage
|
|
51
|
+
)
|
|
52
|
+
// The string overload inherits the replaced run's attributes, which is
|
|
53
|
+
// exactly what keeps the structure the keyboard's replacement dropped.
|
|
54
|
+
patched.replaceCharacters(in: range, with: replacementText)
|
|
55
|
+
return patched
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
func nativeTextMutationFromAuthorizedDiff(
|
|
59
|
+
currentText: String
|
|
60
|
+
) -> NativeTextMutation? {
|
|
61
|
+
let authorizedText = lastAuthorizedText
|
|
62
|
+
guard currentText != authorizedText else { return nil }
|
|
63
|
+
|
|
64
|
+
let authorized = authorizedText as NSString
|
|
65
|
+
let current = currentText as NSString
|
|
66
|
+
let sharedLength = min(authorized.length, current.length)
|
|
67
|
+
var prefix = 0
|
|
68
|
+
while prefix < sharedLength,
|
|
69
|
+
authorized.character(at: prefix) == current.character(at: prefix) {
|
|
70
|
+
prefix += 1
|
|
71
|
+
}
|
|
72
|
+
prefix = sharedUtf16ScalarBoundary(atOrBefore: prefix, in: authorizedText, and: currentText)
|
|
73
|
+
|
|
74
|
+
var authorizedEnd = authorized.length
|
|
75
|
+
var currentEnd = current.length
|
|
76
|
+
while authorizedEnd > prefix,
|
|
77
|
+
currentEnd > prefix,
|
|
78
|
+
authorized.character(at: authorizedEnd - 1) == current.character(at: currentEnd - 1) {
|
|
79
|
+
authorizedEnd -= 1
|
|
80
|
+
currentEnd -= 1
|
|
81
|
+
}
|
|
82
|
+
authorizedEnd = utf16ScalarBoundary(atOrAfter: authorizedEnd, in: authorizedText)
|
|
83
|
+
currentEnd = utf16ScalarBoundary(atOrAfter: currentEnd, in: currentText)
|
|
84
|
+
|
|
85
|
+
let replacementLength = currentEnd - prefix
|
|
86
|
+
guard replacementLength >= 0 else { return nil }
|
|
87
|
+
let rawReplacementText = current.substring(
|
|
88
|
+
with: NSRange(location: prefix, length: replacementLength)
|
|
89
|
+
)
|
|
90
|
+
|
|
91
|
+
let rawSelectionUtf16Range = selectedUtf16Range()
|
|
92
|
+
let authorizedSelectionUtf16Range = lastAuthorizedSelectedUtf16Range
|
|
93
|
+
let preservesAcceptedSpace = shouldPreserveAcceptedAutocorrectSpace(
|
|
94
|
+
authorizedText: authorized,
|
|
95
|
+
replacementStartUtf16: prefix,
|
|
96
|
+
authorizedEndUtf16: authorizedEnd,
|
|
97
|
+
replacementText: rawReplacementText,
|
|
98
|
+
rawSelectionUtf16Range: rawSelectionUtf16Range,
|
|
99
|
+
authorizedSelectionUtf16Range: authorizedSelectionUtf16Range,
|
|
100
|
+
acceptedCaretUtf16Offset: currentEnd
|
|
101
|
+
)
|
|
102
|
+
let replacementText = preservesAcceptedSpace
|
|
103
|
+
? rawReplacementText + " "
|
|
104
|
+
: rawReplacementText
|
|
105
|
+
let selectionRangeForMapping = preservesAcceptedSpace
|
|
106
|
+
? NSRange(location: currentEnd + 1, length: 0)
|
|
107
|
+
: rawSelectionUtf16Range
|
|
108
|
+
let targetSelectionUtf16Range = targetSelectionUtf16RangeForNativeTextMutation(
|
|
109
|
+
rawSelectionUtf16Range: selectionRangeForMapping,
|
|
110
|
+
authorizedSelectionUtf16Range: authorizedSelectionUtf16Range,
|
|
111
|
+
replacementStartUtf16: prefix,
|
|
112
|
+
authorizedEndUtf16: authorizedEnd,
|
|
113
|
+
currentEndUtf16: currentEnd + (preservesAcceptedSpace ? 1 : 0),
|
|
114
|
+
currentTextUtf16Length: current.length + (preservesAcceptedSpace ? 1 : 0)
|
|
115
|
+
)
|
|
116
|
+
let mappedAuthorizedSelectionUtf16Range = targetSelectionUtf16RangeForNativeTextMutation(
|
|
117
|
+
rawSelectionUtf16Range: authorizedSelectionUtf16Range,
|
|
118
|
+
authorizedSelectionUtf16Range: authorizedSelectionUtf16Range,
|
|
119
|
+
replacementStartUtf16: prefix,
|
|
120
|
+
authorizedEndUtf16: authorizedEnd,
|
|
121
|
+
currentEndUtf16: currentEnd + (preservesAcceptedSpace ? 1 : 0),
|
|
122
|
+
currentTextUtf16Length: current.length + (preservesAcceptedSpace ? 1 : 0)
|
|
123
|
+
)
|
|
124
|
+
let authorizedReplacementUtf16Range = NSRange(
|
|
125
|
+
location: prefix,
|
|
126
|
+
length: authorizedEnd - prefix
|
|
127
|
+
)
|
|
128
|
+
let selectedScalarRange = targetSelectionUtf16Range.map { range in
|
|
129
|
+
scalarRange(
|
|
130
|
+
forUtf16Range: range,
|
|
131
|
+
in: authorizedStorageApplying(
|
|
132
|
+
replacementText,
|
|
133
|
+
inUtf16Range: authorizedReplacementUtf16Range
|
|
134
|
+
)
|
|
135
|
+
)
|
|
136
|
+
}
|
|
137
|
+
let preservesAuthorizedSelectionDirection = lastAuthorizedSelectionIsBackward
|
|
138
|
+
&& targetSelectionUtf16Range.map { targetSelection in
|
|
139
|
+
mappedAuthorizedSelectionUtf16Range.map {
|
|
140
|
+
NSEqualRanges(targetSelection, $0)
|
|
141
|
+
} ?? false
|
|
142
|
+
} == true
|
|
143
|
+
let capturedAfterBlur = canAdoptNativeTextMutationAfterBlur()
|
|
144
|
+
|
|
145
|
+
return NativeTextMutation(
|
|
146
|
+
from: PositionBridge.utf16OffsetToScalar(prefix, in: lastAuthorizedAttributedTextStorage),
|
|
147
|
+
to: PositionBridge.utf16OffsetToScalar(authorizedEnd, in: lastAuthorizedAttributedTextStorage),
|
|
148
|
+
authorizedReplacementUtf16Range: authorizedReplacementUtf16Range,
|
|
149
|
+
replacementText: replacementText,
|
|
150
|
+
resultingText: currentText,
|
|
151
|
+
authorizedText: authorizedText,
|
|
152
|
+
selectionAnchor: preservesAuthorizedSelectionDirection
|
|
153
|
+
? selectedScalarRange?.to
|
|
154
|
+
: selectedScalarRange?.from,
|
|
155
|
+
selectionHead: preservesAuthorizedSelectionDirection
|
|
156
|
+
? selectedScalarRange?.from
|
|
157
|
+
: selectedScalarRange?.to,
|
|
158
|
+
authorizedSelectionUtf16Range: authorizedSelectionUtf16Range,
|
|
159
|
+
rawSelectionUtf16Range: rawSelectionUtf16Range,
|
|
160
|
+
acceptedSpaceCaretUtf16Offset: preservesAcceptedSpace ? currentEnd : nil,
|
|
161
|
+
selectionRevision: selectionRevision,
|
|
162
|
+
capturedWhileFirstResponder: isFirstResponder || capturedAfterBlur,
|
|
163
|
+
capturedWhileEditable: isEditable,
|
|
164
|
+
capturedAfterBlur: capturedAfterBlur,
|
|
165
|
+
inputGeneration: nativeTextMutationGeneration
|
|
166
|
+
)
|
|
167
|
+
}
|
|
168
|
+
|
|
169
|
+
func shouldPreserveAcceptedAutocorrectSpace(
|
|
170
|
+
authorizedText: NSString,
|
|
171
|
+
replacementStartUtf16: Int,
|
|
172
|
+
authorizedEndUtf16: Int,
|
|
173
|
+
replacementText: String,
|
|
174
|
+
rawSelectionUtf16Range: NSRange?,
|
|
175
|
+
authorizedSelectionUtf16Range: NSRange?,
|
|
176
|
+
acceptedCaretUtf16Offset: Int
|
|
177
|
+
) -> Bool {
|
|
178
|
+
guard replacementStartUtf16 >= 0,
|
|
179
|
+
authorizedEndUtf16 > replacementStartUtf16,
|
|
180
|
+
authorizedEndUtf16 <= authorizedText.length,
|
|
181
|
+
authorizedText.character(at: authorizedEndUtf16 - 1) == 0x20,
|
|
182
|
+
!replacementText.isEmpty,
|
|
183
|
+
let replacementLastCharacter = replacementText.last,
|
|
184
|
+
replacementLastCharacter.isLetter || replacementLastCharacter.isNumber,
|
|
185
|
+
let rawSelectionUtf16Range,
|
|
186
|
+
rawSelectionUtf16Range.length == 0,
|
|
187
|
+
rawSelectionUtf16Range.location == acceptedCaretUtf16Offset,
|
|
188
|
+
let authorizedSelectionUtf16Range,
|
|
189
|
+
authorizedSelectionUtf16Range.length == 0,
|
|
190
|
+
authorizedSelectionUtf16Range.location == authorizedEndUtf16
|
|
191
|
+
else {
|
|
192
|
+
return false
|
|
193
|
+
}
|
|
194
|
+
|
|
195
|
+
let correctedText = authorizedText.substring(
|
|
196
|
+
with: NSRange(
|
|
197
|
+
location: replacementStartUtf16,
|
|
198
|
+
length: authorizedEndUtf16 - replacementStartUtf16 - 1
|
|
199
|
+
)
|
|
200
|
+
)
|
|
201
|
+
guard !correctedText.isEmpty,
|
|
202
|
+
correctedText != replacementText,
|
|
203
|
+
let correctedLastCharacter = correctedText.last
|
|
204
|
+
else {
|
|
205
|
+
return false
|
|
206
|
+
}
|
|
207
|
+
return correctedLastCharacter.isLetter || correctedLastCharacter.isNumber
|
|
208
|
+
}
|
|
209
|
+
|
|
210
|
+
func nativeTextMutationWithCurrentSelection(
|
|
211
|
+
_ mutation: NativeTextMutation
|
|
212
|
+
) -> NativeTextMutation {
|
|
213
|
+
let currentSelectionUtf16Range = selectedUtf16Range()
|
|
214
|
+
let didSelectionChangeAfterCapture = selectionRevision != mutation.selectionRevision
|
|
215
|
+
let didCurrentRangeMoveAfterCapture: Bool
|
|
216
|
+
if let currentSelectionUtf16Range,
|
|
217
|
+
let rawSelectionUtf16Range = mutation.rawSelectionUtf16Range {
|
|
218
|
+
didCurrentRangeMoveAfterCapture = !NSEqualRanges(
|
|
219
|
+
currentSelectionUtf16Range,
|
|
220
|
+
rawSelectionUtf16Range
|
|
221
|
+
)
|
|
222
|
+
} else {
|
|
223
|
+
didCurrentRangeMoveAfterCapture = false
|
|
224
|
+
}
|
|
225
|
+
let currentSelectionDiffersFromAuthorized: Bool
|
|
226
|
+
if let currentSelectionUtf16Range,
|
|
227
|
+
let authorizedSelectionUtf16Range = mutation.authorizedSelectionUtf16Range {
|
|
228
|
+
currentSelectionDiffersFromAuthorized = !NSEqualRanges(
|
|
229
|
+
currentSelectionUtf16Range,
|
|
230
|
+
authorizedSelectionUtf16Range
|
|
231
|
+
)
|
|
232
|
+
} else {
|
|
233
|
+
currentSelectionDiffersFromAuthorized = currentSelectionUtf16Range != nil
|
|
234
|
+
}
|
|
235
|
+
let repeatsCapturedTransientBeginningSelection: Bool
|
|
236
|
+
if let currentSelectionUtf16Range,
|
|
237
|
+
let rawSelectionUtf16Range = mutation.rawSelectionUtf16Range,
|
|
238
|
+
let authorizedSelectionUtf16Range = mutation.authorizedSelectionUtf16Range,
|
|
239
|
+
NSEqualRanges(currentSelectionUtf16Range, rawSelectionUtf16Range) {
|
|
240
|
+
repeatsCapturedTransientBeginningSelection =
|
|
241
|
+
isTransientBeginningSelectionDuringNativeReplacement(
|
|
242
|
+
currentSelectionUtf16Range,
|
|
243
|
+
authorizedSelection: authorizedSelectionUtf16Range,
|
|
244
|
+
replacementStartUtf16: mutation.authorizedReplacementUtf16Range.location,
|
|
245
|
+
authorizedEndUtf16: NSMaxRange(mutation.authorizedReplacementUtf16Range),
|
|
246
|
+
currentEndUtf16: mutation.authorizedReplacementUtf16Range.location
|
|
247
|
+
+ mutation.replacementText.utf16.count
|
|
248
|
+
)
|
|
249
|
+
} else {
|
|
250
|
+
repeatsCapturedTransientBeginningSelection = false
|
|
251
|
+
}
|
|
252
|
+
let shouldUseCurrentSelection = currentSelectionUtf16Range != nil
|
|
253
|
+
&& !repeatsCapturedTransientBeginningSelection
|
|
254
|
+
&& (
|
|
255
|
+
(didSelectionChangeAfterCapture && currentSelectionDiffersFromAuthorized)
|
|
256
|
+
|| didCurrentRangeMoveAfterCapture
|
|
257
|
+
|| mutation.rawSelectionUtf16Range == nil
|
|
258
|
+
)
|
|
259
|
+
// Same ruler as the capture path: the live view has lost the
|
|
260
|
+
// structural attributes wherever the keyboard replaced a run, so a
|
|
261
|
+
// caret converted against it maps as though the block were never
|
|
262
|
+
// wrapped.
|
|
263
|
+
let selectionConversionStorage = authorizedStorageApplying(
|
|
264
|
+
mutation.replacementText,
|
|
265
|
+
inUtf16Range: mutation.authorizedReplacementUtf16Range
|
|
266
|
+
)
|
|
267
|
+
let selectionRangeForConversion: NSRange?
|
|
268
|
+
if let currentSelectionUtf16Range,
|
|
269
|
+
currentSelectionUtf16Range.length == 0,
|
|
270
|
+
currentSelectionUtf16Range.location == mutation.acceptedSpaceCaretUtf16Offset {
|
|
271
|
+
selectionRangeForConversion = NSRange(
|
|
272
|
+
location: currentSelectionUtf16Range.location + 1,
|
|
273
|
+
length: 0
|
|
274
|
+
)
|
|
275
|
+
} else {
|
|
276
|
+
selectionRangeForConversion = currentSelectionUtf16Range
|
|
277
|
+
}
|
|
278
|
+
let selectedScalarRange = shouldUseCurrentSelection
|
|
279
|
+
? selectionRangeForConversion.map {
|
|
280
|
+
scalarRange(forUtf16Range: $0, in: selectionConversionStorage)
|
|
281
|
+
}
|
|
282
|
+
: nil
|
|
283
|
+
let preservesCapturedSelectionDirection = selectedScalarRange.map { selectedRange in
|
|
284
|
+
guard let anchor = mutation.selectionAnchor,
|
|
285
|
+
let head = mutation.selectionHead,
|
|
286
|
+
anchor > head
|
|
287
|
+
else {
|
|
288
|
+
return false
|
|
289
|
+
}
|
|
290
|
+
return selectedRange.from == head && selectedRange.to == anchor
|
|
291
|
+
} ?? false
|
|
292
|
+
return NativeTextMutation(
|
|
293
|
+
from: mutation.from,
|
|
294
|
+
to: mutation.to,
|
|
295
|
+
authorizedReplacementUtf16Range: mutation.authorizedReplacementUtf16Range,
|
|
296
|
+
replacementText: mutation.replacementText,
|
|
297
|
+
resultingText: mutation.resultingText,
|
|
298
|
+
authorizedText: mutation.authorizedText,
|
|
299
|
+
selectionAnchor: preservesCapturedSelectionDirection
|
|
300
|
+
? selectedScalarRange?.to
|
|
301
|
+
: selectedScalarRange?.from ?? mutation.selectionAnchor,
|
|
302
|
+
selectionHead: preservesCapturedSelectionDirection
|
|
303
|
+
? selectedScalarRange?.from
|
|
304
|
+
: selectedScalarRange?.to ?? mutation.selectionHead,
|
|
305
|
+
authorizedSelectionUtf16Range: mutation.authorizedSelectionUtf16Range,
|
|
306
|
+
rawSelectionUtf16Range: shouldUseCurrentSelection
|
|
307
|
+
? currentSelectionUtf16Range
|
|
308
|
+
: mutation.rawSelectionUtf16Range,
|
|
309
|
+
acceptedSpaceCaretUtf16Offset: mutation.acceptedSpaceCaretUtf16Offset,
|
|
310
|
+
selectionRevision: shouldUseCurrentSelection
|
|
311
|
+
? selectionRevision
|
|
312
|
+
: mutation.selectionRevision,
|
|
313
|
+
capturedWhileFirstResponder: mutation.capturedWhileFirstResponder,
|
|
314
|
+
capturedWhileEditable: mutation.capturedWhileEditable,
|
|
315
|
+
capturedAfterBlur: mutation.capturedAfterBlur,
|
|
316
|
+
inputGeneration: mutation.inputGeneration
|
|
317
|
+
)
|
|
318
|
+
}
|
|
319
|
+
|
|
320
|
+
private func targetSelectionUtf16RangeForNativeTextMutation(
|
|
321
|
+
rawSelectionUtf16Range: NSRange?,
|
|
322
|
+
authorizedSelectionUtf16Range: NSRange?,
|
|
323
|
+
replacementStartUtf16: Int,
|
|
324
|
+
authorizedEndUtf16: Int,
|
|
325
|
+
currentEndUtf16: Int,
|
|
326
|
+
currentTextUtf16Length: Int
|
|
327
|
+
) -> NSRange? {
|
|
328
|
+
guard let authorizedSelection = authorizedSelectionUtf16Range else {
|
|
329
|
+
return clampedUtf16Range(rawSelectionUtf16Range, length: currentTextUtf16Length)
|
|
330
|
+
}
|
|
331
|
+
guard authorizedSelection.location != NSNotFound else {
|
|
332
|
+
return clampedUtf16Range(rawSelectionUtf16Range, length: currentTextUtf16Length)
|
|
333
|
+
}
|
|
334
|
+
|
|
335
|
+
if let rawSelection = rawSelectionUtf16Range,
|
|
336
|
+
rawSelection.location != NSNotFound,
|
|
337
|
+
!isTransientBeginningSelectionDuringNativeReplacement(
|
|
338
|
+
rawSelection,
|
|
339
|
+
authorizedSelection: authorizedSelection,
|
|
340
|
+
replacementStartUtf16: replacementStartUtf16,
|
|
341
|
+
authorizedEndUtf16: authorizedEndUtf16,
|
|
342
|
+
currentEndUtf16: currentEndUtf16
|
|
343
|
+
),
|
|
344
|
+
!NSEqualRanges(rawSelection, authorizedSelection) {
|
|
345
|
+
return clampedUtf16Range(rawSelection, length: currentTextUtf16Length)
|
|
346
|
+
}
|
|
347
|
+
|
|
348
|
+
if authorizedSelection.length == 0 {
|
|
349
|
+
let mappedOffset = mapCollapsedAuthorizedSelectionOffsetThroughNativeTextMutation(
|
|
350
|
+
authorizedSelection.location,
|
|
351
|
+
replacementStartUtf16: replacementStartUtf16,
|
|
352
|
+
authorizedEndUtf16: authorizedEndUtf16,
|
|
353
|
+
currentEndUtf16: currentEndUtf16
|
|
354
|
+
)
|
|
355
|
+
let clampedOffset = min(max(mappedOffset, 0), currentTextUtf16Length)
|
|
356
|
+
return NSRange(location: clampedOffset, length: 0)
|
|
357
|
+
}
|
|
358
|
+
|
|
359
|
+
let mappedStart = mapAuthorizedSelectionOffsetThroughNativeTextMutation(
|
|
360
|
+
authorizedSelection.location,
|
|
361
|
+
replacementStartUtf16: replacementStartUtf16,
|
|
362
|
+
authorizedEndUtf16: authorizedEndUtf16,
|
|
363
|
+
currentEndUtf16: currentEndUtf16,
|
|
364
|
+
isRangeStart: true
|
|
365
|
+
)
|
|
366
|
+
let mappedEnd = mapAuthorizedSelectionOffsetThroughNativeTextMutation(
|
|
367
|
+
NSMaxRange(authorizedSelection),
|
|
368
|
+
replacementStartUtf16: replacementStartUtf16,
|
|
369
|
+
authorizedEndUtf16: authorizedEndUtf16,
|
|
370
|
+
currentEndUtf16: currentEndUtf16,
|
|
371
|
+
isRangeStart: false
|
|
372
|
+
)
|
|
373
|
+
let start = min(mappedStart, mappedEnd)
|
|
374
|
+
let end = max(mappedStart, mappedEnd)
|
|
375
|
+
let clampedStart = min(max(start, 0), currentTextUtf16Length)
|
|
376
|
+
let clampedEnd = min(max(end, 0), currentTextUtf16Length)
|
|
377
|
+
return NSRange(location: clampedStart, length: max(0, clampedEnd - clampedStart))
|
|
378
|
+
}
|
|
379
|
+
|
|
380
|
+
private func isTransientBeginningSelectionDuringNativeReplacement(
|
|
381
|
+
_ rawSelection: NSRange,
|
|
382
|
+
authorizedSelection: NSRange,
|
|
383
|
+
replacementStartUtf16: Int,
|
|
384
|
+
authorizedEndUtf16: Int,
|
|
385
|
+
currentEndUtf16: Int
|
|
386
|
+
) -> Bool {
|
|
387
|
+
rawSelection.location == 0
|
|
388
|
+
&& rawSelection.length == 0
|
|
389
|
+
&& authorizedSelection.location > 0
|
|
390
|
+
&& authorizedSelection.length == 0
|
|
391
|
+
&& authorizedEndUtf16 > replacementStartUtf16
|
|
392
|
+
&& currentEndUtf16 > replacementStartUtf16
|
|
393
|
+
}
|
|
394
|
+
|
|
395
|
+
private func clampedUtf16Range(_ range: NSRange?, length: Int) -> NSRange? {
|
|
396
|
+
guard let range, range.location != NSNotFound else { return nil }
|
|
397
|
+
let start = min(max(range.location, 0), length)
|
|
398
|
+
let end = min(max(NSMaxRange(range), 0), length)
|
|
399
|
+
return NSRange(location: min(start, end), length: abs(end - start))
|
|
400
|
+
}
|
|
401
|
+
|
|
402
|
+
private func mapCollapsedAuthorizedSelectionOffsetThroughNativeTextMutation(
|
|
403
|
+
_ offset: Int,
|
|
404
|
+
replacementStartUtf16: Int,
|
|
405
|
+
authorizedEndUtf16: Int,
|
|
406
|
+
currentEndUtf16: Int
|
|
407
|
+
) -> Int {
|
|
408
|
+
// UIKit can leave a stale caret at the insertion point during autocomplete.
|
|
409
|
+
// A collapsed authorized caret should stay collapsed after the inserted text.
|
|
410
|
+
if replacementStartUtf16 == authorizedEndUtf16,
|
|
411
|
+
offset == replacementStartUtf16,
|
|
412
|
+
currentEndUtf16 > replacementStartUtf16 {
|
|
413
|
+
return currentEndUtf16
|
|
414
|
+
}
|
|
415
|
+
if offset <= replacementStartUtf16 {
|
|
416
|
+
return offset
|
|
417
|
+
}
|
|
418
|
+
if offset < authorizedEndUtf16 {
|
|
419
|
+
return currentEndUtf16
|
|
420
|
+
}
|
|
421
|
+
return offset + currentEndUtf16 - authorizedEndUtf16
|
|
422
|
+
}
|
|
423
|
+
|
|
424
|
+
private func mapAuthorizedSelectionOffsetThroughNativeTextMutation(
|
|
425
|
+
_ offset: Int,
|
|
426
|
+
replacementStartUtf16: Int,
|
|
427
|
+
authorizedEndUtf16: Int,
|
|
428
|
+
currentEndUtf16: Int,
|
|
429
|
+
isRangeStart: Bool
|
|
430
|
+
) -> Int {
|
|
431
|
+
if offset <= replacementStartUtf16 {
|
|
432
|
+
return offset
|
|
433
|
+
}
|
|
434
|
+
if offset >= authorizedEndUtf16 {
|
|
435
|
+
return offset + currentEndUtf16 - authorizedEndUtf16
|
|
436
|
+
}
|
|
437
|
+
return isRangeStart ? replacementStartUtf16 : currentEndUtf16
|
|
438
|
+
}
|
|
439
|
+
|
|
440
|
+
func isUtf16ScalarBoundary(_ offset: Int, in text: String) -> Bool {
|
|
441
|
+
guard offset >= 0, offset <= text.utf16.count else { return false }
|
|
442
|
+
let utf16Index = text.utf16.index(text.utf16.startIndex, offsetBy: offset)
|
|
443
|
+
return String.Index(utf16Index, within: text) != nil
|
|
444
|
+
}
|
|
445
|
+
|
|
446
|
+
private func utf16ScalarBoundary(atOrBefore offset: Int, in text: String) -> Int {
|
|
447
|
+
var candidate = min(max(offset, 0), text.utf16.count)
|
|
448
|
+
while candidate > 0, !isUtf16ScalarBoundary(candidate, in: text) {
|
|
449
|
+
candidate -= 1
|
|
450
|
+
}
|
|
451
|
+
return candidate
|
|
452
|
+
}
|
|
453
|
+
|
|
454
|
+
private func utf16ScalarBoundary(atOrAfter offset: Int, in text: String) -> Int {
|
|
455
|
+
var candidate = min(max(offset, 0), text.utf16.count)
|
|
456
|
+
while candidate < text.utf16.count, !isUtf16ScalarBoundary(candidate, in: text) {
|
|
457
|
+
candidate += 1
|
|
458
|
+
}
|
|
459
|
+
return candidate
|
|
460
|
+
}
|
|
461
|
+
|
|
462
|
+
func sharedUtf16ScalarBoundary(atOrBefore offset: Int, in lhs: String, and rhs: String) -> Int {
|
|
463
|
+
var candidate = min(max(offset, 0), lhs.utf16.count, rhs.utf16.count)
|
|
464
|
+
while candidate > 0,
|
|
465
|
+
!isUtf16ScalarBoundary(candidate, in: lhs) || !isUtf16ScalarBoundary(candidate, in: rhs) {
|
|
466
|
+
candidate -= 1
|
|
467
|
+
}
|
|
468
|
+
return candidate
|
|
469
|
+
}
|
|
470
|
+
|
|
471
|
+
}
|
|
@@ -0,0 +1,97 @@
|
|
|
1
|
+
import UIKit
|
|
2
|
+
|
|
3
|
+
// MARK: - EditorTextView + NSTextStorageDelegate (Reconciliation Fallback)
|
|
4
|
+
|
|
5
|
+
extension EditorTextView: NSTextStorageDelegate {
|
|
6
|
+
|
|
7
|
+
/// Detect unauthorized text storage mutations after UIKit finishes
|
|
8
|
+
/// processing an editing operation. If the text storage diverges from
|
|
9
|
+
/// the last Rust-authorized content and the change was NOT initiated by
|
|
10
|
+
/// our Rust apply path, re-render from Rust ("Rust wins").
|
|
11
|
+
func textStorage(
|
|
12
|
+
_ textStorage: NSTextStorage,
|
|
13
|
+
didProcessEditing editedMask: NSTextStorage.EditActions,
|
|
14
|
+
range editedRange: NSRange,
|
|
15
|
+
changeInLength delta: Int
|
|
16
|
+
) {
|
|
17
|
+
guard editedMask.contains(.editedCharacters) else { return }
|
|
18
|
+
// Skip if this change came from our own Rust apply path, transient IME
|
|
19
|
+
// composition, or an inline prediction. iOS inline predictions (iOS 17+)
|
|
20
|
+
// mutate textStorage directly and set markedTextRange without calling
|
|
21
|
+
// setMarkedText, so isComposing remains false — check markedTextRange too.
|
|
22
|
+
guard !isApplyingRustState, !isComposing, markedTextRange == nil else { return }
|
|
23
|
+
|
|
24
|
+
if case let .awaitingUIKitCleanup(_, _, cleanupRanges) = localTextDragState,
|
|
25
|
+
delta < 0,
|
|
26
|
+
cleanupRanges.contains(where: {
|
|
27
|
+
$0.location == editedRange.location && $0.length == -delta
|
|
28
|
+
}) {
|
|
29
|
+
pendingNativeTextMutation = nil
|
|
30
|
+
nativeTextMutationCommitScheduled = false
|
|
31
|
+
restoreAfterLocalTextDragCleanup()
|
|
32
|
+
return
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
guard editorId != 0 else { return }
|
|
36
|
+
|
|
37
|
+
PositionBridge.invalidateCache(for: self)
|
|
38
|
+
|
|
39
|
+
let currentText = textStorage.string
|
|
40
|
+
guard currentText != lastAuthorizedText else { return }
|
|
41
|
+
currentTopLevelChildMetadata = nil
|
|
42
|
+
|
|
43
|
+
let allowAfterBlur = canAdoptNativeTextMutationAfterBlur()
|
|
44
|
+
if let mutation = nativeTextMutationFromAuthorizedDiff(currentText: currentText),
|
|
45
|
+
isInterceptingInput
|
|
46
|
+
|| shouldAdoptNativeTextStorageMutation(
|
|
47
|
+
mutation,
|
|
48
|
+
allowAfterBlur: allowAfterBlur
|
|
49
|
+
) {
|
|
50
|
+
scheduleNativeTextMutationCommit(mutation)
|
|
51
|
+
return
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
let authorizedPreview = preview(lastAuthorizedText)
|
|
55
|
+
let storagePreview = preview(currentText)
|
|
56
|
+
|
|
57
|
+
reconciliationCount += 1
|
|
58
|
+
|
|
59
|
+
Self.reconciliationLog.warning(
|
|
60
|
+
"""
|
|
61
|
+
[NativeEditor:reconciliation] Text storage diverged from Rust state \
|
|
62
|
+
(count: \(self.reconciliationCount), \
|
|
63
|
+
delta: \(delta), \
|
|
64
|
+
editedRange: \(editedRange.location)..<\(editedRange.location + editedRange.length), \
|
|
65
|
+
authorizedLen: \(self.lastAuthorizedText.count), \
|
|
66
|
+
storageLen: \(currentText.count), \
|
|
67
|
+
selection: \(self.selectionSummary(), privacy: .public), \
|
|
68
|
+
interceptedDepth: \(self.interceptedInputDepth), \
|
|
69
|
+
composing: \(self.isComposing), \
|
|
70
|
+
authorizedPreview: \(authorizedPreview, privacy: .public), \
|
|
71
|
+
storagePreview: \(storagePreview, privacy: .public))
|
|
72
|
+
"""
|
|
73
|
+
)
|
|
74
|
+
|
|
75
|
+
scheduleReconciliationFromRust()
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
func scheduleReconciliationFromRust() {
|
|
79
|
+
guard !reconciliationWorkScheduled else { return }
|
|
80
|
+
reconciliationWorkScheduled = true
|
|
81
|
+
|
|
82
|
+
DispatchQueue.main.async { [weak self] in
|
|
83
|
+
guard let self else { return }
|
|
84
|
+
self.reconciliationWorkScheduled = false
|
|
85
|
+
|
|
86
|
+
guard !self.isApplyingRustState, !self.isInterceptingInput, !self.isComposing else { return }
|
|
87
|
+
guard self.editorId != 0 else { return }
|
|
88
|
+
guard self.textStorage.string != self.lastAuthorizedText else { return }
|
|
89
|
+
|
|
90
|
+
// Reconcile by pulling the current editor state without rebuilding
|
|
91
|
+
// the Rust backend or clearing history. This must run after the
|
|
92
|
+
// current NSTextStorage edit transaction has finished.
|
|
93
|
+
let stateJSON = EditorV2Shadow.getCurrentState(id: self.editorId)
|
|
94
|
+
self.applyUpdateJSON(stateJSON)
|
|
95
|
+
}
|
|
96
|
+
}
|
|
97
|
+
}
|