@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,478 @@
1
+ import UIKit
2
+
3
+ /// The bounded editor owner is the shared native transport/cache implementation.
4
+ /// This alias makes the cross-surface boundary explicit without forking policy.
5
+ typealias NativeImagePipeline = RenderImageLoadOwner
6
+
7
+ /// Immutable geometry produced by preparation. Pixels are deliberately kept
8
+ /// outside `PreparedProseLayout`, so image completion cannot mutate layout.
9
+ struct ViewerImageAttachment: Hashable {
10
+ /// Compiler/admission ceiling. Publication storage is a compact bitset,
11
+ /// but preparation still caps adversarial attachment artifacts.
12
+ static let maximumAdmittedAttachments = 8_192
13
+ /// Ordinal within the immutable prepared artifact. This is the compact
14
+ /// publication-state address; `id` remains source-qualified cache identity.
15
+ let ordinal: Int
16
+ let id: String
17
+ let source: String
18
+ let bounds: CGRect
19
+ let declaredSize: CGSize?
20
+
21
+ init(
22
+ ordinal: Int = -1,
23
+ id: String,
24
+ source: String,
25
+ bounds: CGRect,
26
+ declaredSize: CGSize?
27
+ ) {
28
+ self.ordinal = ordinal
29
+ self.id = id
30
+ self.source = source
31
+ self.bounds = bounds
32
+ self.declaredSize = declaredSize
33
+ }
34
+
35
+ var hasDeclaredSize: Bool { (declaredSize?.width ?? 0) > 0 && (declaredSize?.height ?? 0) > 0 }
36
+
37
+ struct SourceMetadata {
38
+ let id: String
39
+ let source: String
40
+ let declaredSize: CGSize?
41
+ }
42
+
43
+ static func sourceAndDeclaredSize(in block: ViewerBlock) -> SourceMetadata? {
44
+ guard let atom = block.inlines.compactMap({ inline -> (UInt32, String)? in
45
+ guard case let .atom(nodeType, docPos, attrsJSON, _) = inline,
46
+ nodeType == "image" else { return nil }
47
+ return (docPos, attrsJSON)
48
+ }).first,
49
+ let values = try? JSONSerialization.jsonObject(with: Data(atom.1.utf8)) as? [String: Any],
50
+ let source = values["src"] as? String, !source.isEmpty else { return nil }
51
+ func dimension(_ name: String) -> CGFloat? {
52
+ guard let value = values[name] as? NSNumber else { return nil }
53
+ let dimension = CGFloat(truncating: value)
54
+ return dimension.isFinite && dimension > 0 ? dimension : nil
55
+ }
56
+ let width = dimension("width")
57
+ let height = dimension("height")
58
+ let declared = width.flatMap { declaredWidth in height.map { CGSize(width: declaredWidth, height: $0) } }
59
+ return SourceMetadata(id: "\(atom.0):\(source)", source: source, declaredSize: declared)
60
+ }
61
+ }
62
+
63
+ /// The only mutable image-metadata state. It records the first valid intrinsic
64
+ /// size atomically and advances the attachment revision exactly once per id.
65
+ final class ViewerImageIntrinsicStore {
66
+ static let shared = ViewerImageIntrinsicStore()
67
+
68
+ private struct Entry {
69
+ let size: CGSize
70
+ var access: UInt64
71
+ }
72
+
73
+ private let lock = NSLock()
74
+ private var entryLimit: Int
75
+ private var access: UInt64 = 0
76
+ private var values: [String: Entry] = [:]
77
+
78
+ init(entryLimit: Int = 256) { self.entryLimit = max(1, entryLimit) }
79
+
80
+ /// Preparation may only see its explicitly scoped local sidecar. The
81
+ /// process cache remains global, but an LRU miss never scans another host.
82
+ func size(for id: String) -> CGSize? {
83
+ lock.lock()
84
+ if var entry = values[id] {
85
+ access &+= 1
86
+ entry.access = access
87
+ values[id] = entry
88
+ lock.unlock()
89
+ return entry.size
90
+ }
91
+ lock.unlock()
92
+ return FabricAttachmentSidecars.currentMeasurementState?.intrinsicSize(forSourceQualifiedID: id)
93
+ }
94
+
95
+ /// Test-only global-LRU inspection. `size(for:)` may consult its scoped
96
+ /// owner, so it cannot prove an LRU eviction on its own.
97
+ func globalSize(for id: String) -> CGSize? {
98
+ lock.withLock { values[id]?.size }
99
+ }
100
+
101
+ /// Test-only control of the actual process-global LRU. `size(for:)` keeps
102
+ /// its scoped-sidecar fallback, while this inspection proves eviction.
103
+ func clearAndSetEntryLimitForTesting(_ limit: Int = 256) {
104
+ lock.withLock {
105
+ entryLimit = max(1, limit)
106
+ access = 0
107
+ values.removeAll(keepingCapacity: false)
108
+ }
109
+ }
110
+
111
+ func store(_ size: CGSize, for id: String) {
112
+ guard size.width.isFinite, size.height.isFinite, size.width > 0, size.height > 0 else { return }
113
+ lock.lock()
114
+ defer { lock.unlock() }
115
+ access &+= 1
116
+ values[id] = Entry(size: size, access: access)
117
+ while values.count > entryLimit,
118
+ let oldest = values.min(by: { lhs, rhs in
119
+ lhs.value.access == rhs.value.access ? lhs.key < rhs.key : lhs.value.access < rhs.value.access
120
+ }) {
121
+ values.removeValue(forKey: oldest.key)
122
+ }
123
+ }
124
+ }
125
+
126
+ /// Per-surface publication state. It retains compact ordinal metadata plus a
127
+ /// bitset, so the global LRU is only an optimization. It resets only for a
128
+ /// semantic replacement or recycle/teardown, never request cancellation.
129
+ final class ViewerAttachmentRevisionState {
130
+ /// Project accounting convention: fixed owner plus one header per retained
131
+ /// proportional collection. Payload is charged below at native stride.
132
+ static let fixedRetainedBytes = 160
133
+ static let collectionRetainedBytes = 32
134
+ private let lock = NSLock()
135
+ private var publishedBits: [UInt8] = []
136
+ private var reportedErrorBits: [UInt8] = []
137
+ private var intrinsicSizes: [CGSize] = []
138
+ private var sourceQualifiedIDs: [String?] = []
139
+ private var attachmentOrdinals: [Int] = []
140
+ private var admittedAttachmentCount = 0
141
+ private var semanticGenerationIdentity: String?
142
+ private(set) var revision: UInt64 = 0
143
+
144
+ /// Exact per-surface retained state. This is not an immutable layout cost:
145
+ /// it belongs to the mounted host, including both bitsets, dimensions,
146
+ /// source identity references, ordinal addresses, collection headers, and
147
+ /// explicitly scoped preparation ownership.
148
+ var retainedPublicationBytesForTesting: Int {
149
+ lock.withLock {
150
+ Self.fixedRetainedBytes
151
+ + Self.collectionRetainedBytes * 5
152
+ + publishedBits.count
153
+ + reportedErrorBits.count
154
+ + intrinsicSizes.count * MemoryLayout<CGSize>.stride
155
+ + sourceQualifiedIDs.count * MemoryLayout<String?>.stride
156
+ + attachmentOrdinals.count * MemoryLayout<Int>.stride
157
+ + sourceQualifiedIDs.compactMap { $0 }.reduce(0) { $0 + $1.utf8.count * 2 }
158
+ + (semanticGenerationIdentity?.utf8.count ?? 0) * 2
159
+ }
160
+ }
161
+
162
+ /// Returns true exactly when a true semantic replacement has cleared all
163
+ /// generation-scoped correctness state. State-revision reinstalls return
164
+ /// false and preserve metadata/error publication.
165
+ @discardableResult
166
+ func beginSemanticGeneration(_ identity: String) -> Bool {
167
+ let changed = lock.withLock {
168
+ guard semanticGenerationIdentity != identity else { return false }
169
+ clearLocked()
170
+ semanticGenerationIdentity = identity
171
+ return true
172
+ }
173
+ return changed
174
+ }
175
+
176
+ func admit(attachmentCount: Int) {
177
+ let count = max(0, attachmentCount)
178
+ lock.withLock {
179
+ guard admittedAttachmentCount != count else { return }
180
+ admittedAttachmentCount = count
181
+ publishedBits = Array(repeating: 0, count: (count + 7) / 8)
182
+ reportedErrorBits = Array(repeating: 0, count: (count + 7) / 8)
183
+ intrinsicSizes = Array(repeating: .zero, count: count)
184
+ sourceQualifiedIDs = Array(repeating: nil, count: count)
185
+ attachmentOrdinals = Array(0..<count)
186
+ }
187
+ }
188
+
189
+ func reset() {
190
+ lock.withLock {
191
+ clearLocked()
192
+ semanticGenerationIdentity = nil
193
+ }
194
+ }
195
+
196
+ @discardableResult
197
+ func recordIntrinsicSize(_ size: CGSize, for id: String, ordinal: Int, declaredSize: CGSize?) -> Bool {
198
+ guard declaredSize == nil, size.width.isFinite, size.height.isFinite, size.width > 0, size.height > 0 else { return false }
199
+ lock.lock(); defer { lock.unlock() }
200
+ guard ordinal >= 0, ordinal < admittedAttachmentCount else { return false }
201
+ let byteIndex = ordinal / 8
202
+ let mask = UInt8(1 << (ordinal % 8))
203
+ guard publishedBits[byteIndex] & mask == 0 else { return false }
204
+ publishedBits[byteIndex] |= mask
205
+ intrinsicSizes[ordinal] = size
206
+ sourceQualifiedIDs[ordinal] = id
207
+ ViewerImageIntrinsicStore.shared.store(size, for: id)
208
+ revision &+= 1
209
+ return true
210
+ }
211
+
212
+ func intrinsicSize(for ordinal: Int) -> CGSize? {
213
+ lock.withLock {
214
+ guard ordinal >= 0, ordinal < admittedAttachmentCount else { return nil }
215
+ let mask = UInt8(1 << (ordinal % 8))
216
+ return publishedBits[ordinal / 8] & mask == 0 ? nil : intrinsicSizes[ordinal]
217
+ }
218
+ }
219
+
220
+ @discardableResult
221
+ func recordResourceFailure(for ordinal: Int) -> Bool {
222
+ lock.withLock {
223
+ guard ordinal >= 0, ordinal < admittedAttachmentCount else { return false }
224
+ let byteIndex = ordinal / 8
225
+ let mask = UInt8(1 << (ordinal % 8))
226
+ guard reportedErrorBits[byteIndex] & mask == 0 else { return false }
227
+ reportedErrorBits[byteIndex] |= mask
228
+ return true
229
+ }
230
+ }
231
+
232
+ fileprivate func intrinsicSize(forSourceQualifiedID id: String) -> CGSize? {
233
+ lock.withLock {
234
+ guard let index = sourceQualifiedIDs.firstIndex(where: { $0 == id }) else { return nil }
235
+ let ordinal = attachmentOrdinals[index]
236
+ let mask = UInt8(1 << (ordinal % 8))
237
+ return publishedBits[ordinal / 8] & mask == 0 ? nil : intrinsicSizes[ordinal]
238
+ }
239
+ }
240
+
241
+ private func clearLocked() {
242
+ publishedBits.removeAll(keepingCapacity: false)
243
+ reportedErrorBits.removeAll(keepingCapacity: false)
244
+ intrinsicSizes.removeAll(keepingCapacity: false)
245
+ sourceQualifiedIDs.removeAll(keepingCapacity: false)
246
+ attachmentOrdinals.removeAll(keepingCapacity: false)
247
+ admittedAttachmentCount = 0
248
+ revision = 0
249
+ }
250
+
251
+ }
252
+
253
+ /// Fabric preparation has no mounted UIView to own mutable image publication.
254
+ /// Keep that state at the stable surface/component token and install it into a
255
+ /// thread-local measurement scope before Core Text can inspect intrinsic data.
256
+ final class FabricAttachmentSidecars {
257
+ private static let lock = NSLock()
258
+ private struct Owner: Hashable {
259
+ let surface: FabricSurfaceToken
260
+ let leaseHandle: UInt64
261
+ }
262
+ private static var states: [Owner: ViewerAttachmentRevisionState] = [:]
263
+ private static let measurementStateKey = "com.apollohg.editor.viewer.fabricImageMeasurementState"
264
+
265
+ static var currentMeasurementState: ViewerAttachmentRevisionState? {
266
+ Thread.current.threadDictionary[measurementStateKey] as? ViewerAttachmentRevisionState
267
+ }
268
+
269
+ static func begin(
270
+ _ surface: FabricSurfaceToken,
271
+ leaseHandle: UInt64 = 0,
272
+ semanticIdentity: String
273
+ ) -> ViewerAttachmentRevisionState {
274
+ lock.withLock {
275
+ let owner = Owner(surface: surface, leaseHandle: leaseHandle)
276
+ let state = states[owner] ?? ViewerAttachmentRevisionState()
277
+ states[owner] = state
278
+ _ = state.beginSemanticGeneration(semanticIdentity)
279
+ return state
280
+ }
281
+ }
282
+
283
+ static func withMeasurementState<T>(_ state: ViewerAttachmentRevisionState, _ body: () throws -> T) rethrows -> T {
284
+ let dictionary = Thread.current.threadDictionary
285
+ let previous = dictionary[measurementStateKey]
286
+ dictionary[measurementStateKey] = state
287
+ defer {
288
+ if let previous { dictionary[measurementStateKey] = previous } else { dictionary.removeObject(forKey: measurementStateKey) }
289
+ }
290
+ return try body()
291
+ }
292
+
293
+ static func state(
294
+ for surface: FabricSurfaceToken,
295
+ leaseHandle: UInt64 = 0
296
+ ) -> ViewerAttachmentRevisionState? {
297
+ lock.withLock { states[Owner(surface: surface, leaseHandle: leaseHandle)] }
298
+ }
299
+
300
+ static func remove(_ surface: FabricSurfaceToken, leaseHandle: UInt64? = nil) {
301
+ lock.withLock {
302
+ let owners = states.keys.filter {
303
+ $0.surface == surface && (leaseHandle == nil || $0.leaseHandle == leaseHandle)
304
+ }
305
+ owners.forEach { states.removeValue(forKey: $0)?.reset() }
306
+ }
307
+ }
308
+
309
+ static func remove(surfaceId: Int64) {
310
+ lock.withLock {
311
+ states.keys.filter { $0.surface.surfaceId == surfaceId }.forEach { states.removeValue(forKey: $0)?.reset() }
312
+ }
313
+ }
314
+ }
315
+
316
+ /// Bounded/cancellable viewer facade over the editor's existing native image
317
+ /// owner. The owner retains validation, fetch/decode limits, cache ownership,
318
+ /// receipts, deadlines and error isolation; this facade adds viewport and
319
+ /// generation ownership without changing editor behaviour.
320
+ final class ViewerImagePipeline {
321
+ typealias PixelCompletion = (_ attachment: ViewerImageAttachment, _ image: UIImage) -> Void
322
+ typealias MetadataCompletion = (_ attachment: ViewerImageAttachment, _ size: CGSize) -> Void
323
+
324
+ static let prefetchMargin: CGFloat = 480
325
+
326
+ private let owner: NativeImagePipeline
327
+ private let lock = NSLock()
328
+ private var generation = ""
329
+ private var enabled = false
330
+ private var receipts: [String: NativeImagePipeline.ImageLoadReceipt] = [:]
331
+ private var requested = Set<String>()
332
+ private(set) var requestCountForTesting = 0
333
+ var onPixels: PixelCompletion?
334
+ var onIntrinsicMetadata: MetadataCompletion?
335
+ /// Deliberately carries no source URL; hosts map it to their public error contract.
336
+ var onResourceFailure: ((ViewerImageAttachment) -> Void)?
337
+
338
+ init(policy: ImageLoadingPolicy) {
339
+ owner = NativeImagePipeline(policy: policy)
340
+ }
341
+
342
+ func begin(generation: String, imagesEnabled: Bool, policy: ImageLoadingPolicy? = nil) {
343
+ lock.lock()
344
+ let nextPolicy = policy ?? owner.policy
345
+ if self.generation == generation, enabled == imagesEnabled, owner.policy == nextPolicy {
346
+ lock.unlock()
347
+ return
348
+ }
349
+ owner.cancelAll()
350
+ if owner.policy != nextPolicy { owner.updatePolicy(nextPolicy) }
351
+ self.generation = generation
352
+ enabled = imagesEnabled
353
+ receipts.removeAll()
354
+ requested.removeAll()
355
+ requestCountForTesting = 0
356
+ lock.unlock()
357
+ }
358
+
359
+ func cancel() {
360
+ lock.lock()
361
+ generation = ""
362
+ enabled = false
363
+ receipts.values.forEach { $0.cancel() }
364
+ receipts.removeAll()
365
+ requested.removeAll()
366
+ lock.unlock()
367
+ owner.cancelAll()
368
+ }
369
+
370
+ func acceptsCompletion(generation: String) -> Bool {
371
+ lock.lock(); defer { lock.unlock() }
372
+ return enabled && !self.generation.isEmpty && self.generation == generation
373
+ }
374
+
375
+ @discardableResult
376
+ func updateVisibleRect(_ visibleRect: CGRect, attachments: [ViewerImageAttachment]) -> Set<String> {
377
+ guard visibleRect.origin.x.isFinite, visibleRect.origin.y.isFinite,
378
+ visibleRect.size.width.isFinite, visibleRect.size.height.isFinite,
379
+ !visibleRect.isNull, !visibleRect.isEmpty else { return [] }
380
+ let expanded = visibleRect.insetBy(dx: -Self.prefetchMargin, dy: -Self.prefetchMargin)
381
+ let eligible = attachments.filter { $0.ordinal >= 0 && !$0.source.isEmpty && $0.bounds.intersects(expanded) }
382
+ let eligibleIDs = Set(eligible.map(\.id))
383
+ struct PendingLoads {
384
+ let generation: String
385
+ let attachments: [ViewerImageAttachment]
386
+ let cancellations: [NativeImagePipeline.ImageLoadReceipt]
387
+ }
388
+ let start: PendingLoads? = lock.withLock {
389
+ guard enabled, !generation.isEmpty else { return nil }
390
+ let leaving = requested.subtracting(eligibleIDs)
391
+ let cancellations = leaving.compactMap { receipts.removeValue(forKey: $0) }
392
+ requested.subtract(leaving)
393
+ let next = eligible.filter { requested.insert($0.id).inserted }
394
+ requestCountForTesting += next.count
395
+ return PendingLoads(generation: generation, attachments: next, cancellations: cancellations)
396
+ }
397
+ guard let start else { return eligibleIDs }
398
+ let currentGeneration = start.generation
399
+ start.cancellations.forEach { $0.cancel() }
400
+ for attachment in start.attachments {
401
+ let receipt = owner.startImageLoad(
402
+ source: attachment.source,
403
+ completion: { [weak self] image in
404
+ guard let self,
405
+ self.acceptsCompletion(generation: currentGeneration, attachmentID: attachment.id)
406
+ else { return }
407
+ guard let image else {
408
+ self.reportFailure(attachment, generation: currentGeneration)
409
+ return
410
+ }
411
+ let size = image.size.applying(CGAffineTransform(scaleX: image.scale, y: image.scale))
412
+ guard size.width.isFinite, size.height.isFinite, size.width > 0, size.height > 0 else {
413
+ self.reportFailure(attachment, generation: currentGeneration)
414
+ return
415
+ }
416
+ PreparedProseInstrumentation.imageMetadataRead()
417
+ self.onIntrinsicMetadata?(attachment, size)
418
+ guard self.acceptsCompletion(generation: currentGeneration, attachmentID: attachment.id)
419
+ else { return }
420
+ PreparedProseInstrumentation.imageDecoded()
421
+ self.onPixels?(attachment, image)
422
+ },
423
+ onAcceptedStart: PreparedProseInstrumentation.imageRequested
424
+ )
425
+ if let receipt {
426
+ let shouldRetain = lock.withLock { () -> Bool in
427
+ guard enabled, generation == currentGeneration else { return false }
428
+ receipts[attachment.id] = receipt
429
+ return true
430
+ }
431
+ if !shouldRetain { receipt.cancel() }
432
+ } else {
433
+ reportFailure(attachment, generation: currentGeneration)
434
+ }
435
+ }
436
+ return eligibleIDs
437
+ }
438
+
439
+ func leaveViewport() {
440
+ let cancellations = lock.withLock {
441
+ let values = Array(receipts.values)
442
+ receipts.removeAll()
443
+ requested.removeAll()
444
+ return values
445
+ }
446
+ cancellations.forEach { $0.cancel() }
447
+ }
448
+
449
+ private func acceptsCompletion(generation: String, attachmentID: String) -> Bool {
450
+ lock.withLock {
451
+ enabled && !self.generation.isEmpty && self.generation == generation
452
+ && requested.contains(attachmentID)
453
+ }
454
+ }
455
+
456
+ private func reportFailure(_ attachment: ViewerImageAttachment, generation: String) {
457
+ let callback: ((ViewerImageAttachment) -> Void)? = lock.withLock {
458
+ guard enabled, self.generation == generation else { return nil }
459
+ return onResourceFailure
460
+ }
461
+ callback?(attachment)
462
+ }
463
+
464
+ internal func reportFailureForTesting(_ attachment: ViewerImageAttachment) {
465
+ lock.lock()
466
+ let currentGeneration = generation
467
+ lock.unlock()
468
+ reportFailure(attachment, generation: currentGeneration)
469
+ }
470
+ }
471
+
472
+ private extension NSLock {
473
+ func withLock<T>(_ body: () -> T) -> T {
474
+ lock()
475
+ defer { unlock() }
476
+ return body()
477
+ }
478
+ }