@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,16 @@
1
+ package com.apollohg.editor.viewer
2
+
3
+ import com.facebook.react.ReactPackage
4
+ import com.facebook.react.bridge.NativeModule
5
+ import com.facebook.react.bridge.ReactApplicationContext
6
+ import com.facebook.react.uimanager.ViewManager
7
+
8
+ /** Autolinked package that exposes only the Fabric PreparedProseViewer manager. */
9
+ class PreparedProseViewerPackage : ReactPackage {
10
+ override fun createNativeModules(reactContext: ReactApplicationContext): List<NativeModule> =
11
+ emptyList()
12
+
13
+ override fun createViewManagers(
14
+ reactContext: ReactApplicationContext
15
+ ): List<ViewManager<in Nothing, in Nothing>> = listOf(PreparedProseViewerManager())
16
+ }
@@ -0,0 +1,89 @@
1
+ package com.apollohg.editor.viewer
2
+
3
+ import android.graphics.Rect
4
+ import kotlin.math.abs
5
+ import kotlin.math.ceil
6
+ import org.json.JSONArray
7
+ import org.json.JSONObject
8
+
9
+ internal data class PreparedViewerAtom(
10
+ val nodeType: String,
11
+ val docPos: Long,
12
+ val attrsJson: String,
13
+ val bounds: Rect
14
+ ) {
15
+ val retainedBytes: Long get() = 96L + (nodeType.length + attrsJson.length) * 2L
16
+ }
17
+
18
+ internal data class ViewerAtomConfiguration(
19
+ val generation: String,
20
+ val revision: String,
21
+ val nodeTypes: Set<String>,
22
+ val estimatedHeights: Map<String, Double>,
23
+ val measurements: Map<String, Pair<Double, Double>>
24
+ ) {
25
+ val retainedBytes: Long get() = 192L + (generation.length + revision.length) * 2L +
26
+ nodeTypes.sumOf { 32L + it.length * 2L } +
27
+ estimatedHeights.keys.sumOf { 48L + it.length * 2L } +
28
+ measurements.keys.sumOf { 64L + it.length * 2L }
29
+
30
+ fun heightPx(atom: ViewerInline.Atom, widthPx: Int, density: Float): Int {
31
+ val measured = measurements[atom.docPos.toString()]?.takeIf {
32
+ abs(it.first - widthPx / density.toDouble()) <
33
+ 0.01
34
+ }
35
+ return ceil(
36
+ (measured?.second ?: estimatedHeights[atom.nodeType] ?: 32.0) * density
37
+ ).toInt().coerceAtLeast(0)
38
+ }
39
+
40
+ companion object {
41
+ fun parse(themeJson: String?): ViewerAtomConfiguration? = runCatching {
42
+ val value =
43
+ JSONObject(themeJson ?: return null).optJSONObject("viewerAtoms") ?: return null
44
+ val types = value.optJSONArray("nodeTypes") ?: JSONArray()
45
+ val estimates = value.optJSONObject("estimatedHeights") ?: JSONObject()
46
+ val measurements = value.optJSONObject("measurements") ?: JSONObject()
47
+ ViewerAtomConfiguration(
48
+ value.getString("generation"),
49
+ value.getString("revision"),
50
+ (0 until types.length()).map { types.getString(it) }.toSet(),
51
+ estimates.keys().asSequence().mapNotNull { key ->
52
+ estimates.optDouble(key).takeIf {
53
+ it.isFinite() &&
54
+ it >= 0
55
+ }?.let { key to it }
56
+ }.toMap(),
57
+ measurements.keys().asSequence().mapNotNull { key ->
58
+ val size = measurements.optJSONObject(key) ?: return@mapNotNull null
59
+ val width = size.optDouble("width")
60
+ val height = size.optDouble("height")
61
+ if (width.isFinite() && width >= 0 && height.isFinite() &&
62
+ height >= 0
63
+ ) {
64
+ key to (width to height)
65
+ } else {
66
+ null
67
+ }
68
+ }.toMap()
69
+ )
70
+ }.getOrNull()
71
+ }
72
+ }
73
+
74
+ internal fun PreparedProseLayout.atomsJson(density: Float, originX: Int, originY: Int): String =
75
+ JSONArray().apply {
76
+ viewerAtoms.forEach { atom ->
77
+ put(
78
+ JSONObject().apply {
79
+ put("nodeType", atom.nodeType)
80
+ put("docPos", atom.docPos)
81
+ put("attrsJson", atom.attrsJson)
82
+ put("x", (atom.bounds.left.toDouble() + originX) / density)
83
+ put("y", (atom.bounds.top.toDouble() + originY) / density)
84
+ put("width", atom.bounds.width().toDouble() / density)
85
+ put("height", atom.bounds.height().toDouble() / density)
86
+ }
87
+ )
88
+ }
89
+ }.toString()
@@ -0,0 +1,91 @@
1
+ package com.apollohg.editor.viewer
2
+
3
+ import com.apollohg.editor.CodeHighlightBlock
4
+ import com.apollohg.editor.CodeHighlightRange
5
+ import com.apollohg.editor.CodeHighlightingSession
6
+ import com.apollohg.editor.NativeCodeHighlightingConfig
7
+
8
+ internal object ViewerCodeHighlightCache {
9
+ private val values = LinkedHashMap<String, List<CodeHighlightRange>>(16, .75f, true)
10
+ private var bytes = 0L
11
+ internal fun key(config: NativeCodeHighlightingConfig, block: CodeHighlightBlock) = sha256(
12
+ org.json.JSONArray(
13
+ listOf(config.provider, config.theme, block.language, block.text)
14
+ ).toString()
15
+ )
16
+
17
+ fun get(
18
+ config: NativeCodeHighlightingConfig,
19
+ block: CodeHighlightBlock
20
+ ): List<CodeHighlightRange>? {
21
+ val key = key(config, block)
22
+ return synchronized(values) { values[key] }
23
+ }
24
+
25
+ fun store(
26
+ config: NativeCodeHighlightingConfig,
27
+ block: CodeHighlightBlock,
28
+ ranges: List<CodeHighlightRange>
29
+ ) {
30
+ val key = key(config, block)
31
+ val copy = ranges.toList()
32
+ synchronized(values) {
33
+ values.put(key, copy)?.let { bytes -= 128L + it.size * 32L }
34
+ bytes += 128L + copy.size * 32L
35
+ while (bytes > 8L * 1024 * 1024 || values.size > 512) {
36
+ val oldest = values.entries.first()
37
+ bytes -= 128L + oldest.value.size * 32L
38
+ values.remove(oldest.key)
39
+ }
40
+ }
41
+ }
42
+ }
43
+
44
+ internal class ViewerCodeHighlighting(private val view: PreparedProseDrawingView) {
45
+ private val session = CodeHighlightingSession()
46
+ private var semanticGeneration: String? = null
47
+ private val completed = mutableSetOf<String>()
48
+ private var notifiedArtifact = java.lang.ref.WeakReference<PreparedProseLayout>(null)
49
+ fun cancel() = session.cancel()
50
+ fun update() {
51
+ session.cancel()
52
+ val artifact = view.preparedLayout ?: return
53
+ val config = artifact.codeHighlighting ?: return
54
+ if (semanticGeneration !=
55
+ artifact.key.semanticGenerationIdentity
56
+ ) {
57
+ semanticGeneration =
58
+ artifact.key.semanticGenerationIdentity
59
+ completed.clear()
60
+ }
61
+ if (!view.isAttachedToWindow) return
62
+ val hasUnconsumedCache = artifact.codeHighlightBlocks.any {
63
+ ViewerCodeHighlightCache.key(config, it) !in artifact.highlightedCodeKeys &&
64
+ ViewerCodeHighlightCache.get(config, it) != null
65
+ }
66
+ if (hasUnconsumedCache && notifiedArtifact.get() !== artifact) {
67
+ notifiedArtifact = java.lang.ref.WeakReference(artifact)
68
+ view.onCodeHighlightsReady?.invoke()
69
+ return
70
+ }
71
+ val pending = artifact.codeHighlightBlocks.filter {
72
+ ViewerCodeHighlightCache.get(config, it) ==
73
+ null &&
74
+ ViewerCodeHighlightCache.key(config, it) !in completed
75
+ }
76
+ if (pending.isEmpty()) return
77
+ session.update(config.provider, config.theme, pending) { result ->
78
+ if (!view.isAttachedToWindow || view.preparedLayout !== artifact) return@update
79
+ result.onSuccess { blocks ->
80
+ blocks.forEach {
81
+ ViewerCodeHighlightCache.store(config, it.block, it.ranges)
82
+ completed +=
83
+ ViewerCodeHighlightCache.key(config, it.block)
84
+ }
85
+ view.onCodeHighlightsReady?.invoke()
86
+ }.onFailure {
87
+ android.util.Log.w("NativeProseViewer", "Code highlighting failed: ${it.message}")
88
+ }
89
+ }
90
+ }
91
+ }
@@ -0,0 +1,453 @@
1
+ package com.apollohg.editor.viewer
2
+
3
+ import com.apollohg.editor.ProseViewerConfiguration
4
+ import com.apollohg.editor.ProseViewerError
5
+ import com.apollohg.editor.ProseViewerSource
6
+ import java.security.MessageDigest
7
+ import org.json.JSONObject
8
+ import uniffi.editor_core.FfiViewerCompileRequest
9
+ import uniffi.editor_core.FfiViewerElement
10
+ import uniffi.editor_core.FfiViewerMark
11
+ import uniffi.editor_core.FfiViewerSourceKind
12
+ import uniffi.editor_core.viewerCompile
13
+
14
+ internal data class ViewerListContext(
15
+ val ordered: Boolean,
16
+ /** Rust u32 list index retained exactly for interaction/accessibility consumers. */
17
+ val index: Long,
18
+ val kind: String?,
19
+ val checked: Boolean,
20
+ val isLast: Boolean,
21
+ val isFirst: Boolean = false
22
+ )
23
+
24
+ /** Identifies the nearest list item and its first/final renderable leaf. */
25
+ internal data class ViewerListItemBoundary(
26
+ val identity: Int,
27
+ val nestingDepth: Int,
28
+ val isFirstRenderableLeaf: Boolean,
29
+ val isFinalRenderableLeaf: Boolean
30
+ )
31
+
32
+ /**
33
+ * One list-item owner on a leaf's full semantic path, ordered outermost first.
34
+ * Every owner keeps its own marker reservation even when a nested descendant is
35
+ * the nearest list item exposed to interaction/accessibility consumers.
36
+ */
37
+ internal data class ViewerListItemAncestor(
38
+ val identity: Int,
39
+ val context: ViewerListContext,
40
+ val nestingDepth: Int,
41
+ val isFirstRenderableLeaf: Boolean,
42
+ val isFinalRenderableLeaf: Boolean
43
+ )
44
+
45
+ internal sealed interface ViewerInline {
46
+ data class Text(val text: String, val marks: List<FfiViewerMark>) : ViewerInline
47
+
48
+ /** Rust u32 document position retained exactly; drawing spans never own it. */
49
+ data class Atom(
50
+ val nodeType: String,
51
+ val docPos: Long,
52
+ val attrsJson: String,
53
+ val label: String
54
+ ) : ViewerInline
55
+ }
56
+
57
+ internal data class ViewerContainerAncestor(
58
+ val identity: Int,
59
+ val nodeType: String,
60
+ val firstLeaf: Int,
61
+ val lastLeaf: Int
62
+ )
63
+
64
+ internal data class ViewerBlock(
65
+ val nodeType: String,
66
+ val depth: Int,
67
+ val inBlockquote: Boolean,
68
+ val listContext: ViewerListContext?,
69
+ val listItemBoundary: ViewerListItemBoundary?,
70
+ val inlines: List<ViewerInline>,
71
+ val listItemAncestors: List<ViewerListItemAncestor> = emptyList(),
72
+ val outermostListItemIdentity: Int? = null,
73
+ val outermostListItemIsLast: Boolean = false,
74
+ val isBlockAtom: Boolean = false,
75
+ val containers: List<ViewerContainerAncestor> = emptyList(),
76
+ val language: String? = null
77
+ )
78
+
79
+ /** Semantic positions live only in [ViewerInline.Atom], never in Android drawing spans. */
80
+ internal data class ViewerDocument(
81
+ val semanticKey: String,
82
+ val blocks: List<ViewerBlock>,
83
+ val isEmpty: Boolean,
84
+ val retainedBytes: Long,
85
+ val trailingEmptyTextBlockCount: Int = 0
86
+ )
87
+
88
+ internal data class ProseViewerRequest(
89
+ val source: ProseViewerSource,
90
+ val configuration: ProseViewerConfiguration,
91
+ val nativeFontRevision: Long = 0,
92
+ val fontEnvironmentRevision: Long = 0,
93
+ val attachmentRevision: Long = 0
94
+ ) {
95
+ val compiledCacheKey: String by lazy {
96
+ sha256(
97
+ listOf(
98
+ source.value,
99
+ configuration.configJson,
100
+ configuration.imagePolicyJson.orEmpty(),
101
+ if (configuration.imagesEnabled) "1" else "0",
102
+ mentionPrefix(configuration.configJson).orEmpty(),
103
+ source.kind
104
+ ).joinToString("\u001f")
105
+ )
106
+ }
107
+ val themeDigest: String by lazy { sha256(configuration.themeJson.orEmpty()) }
108
+
109
+ /** Semantic publication identity; layout/font revisions deliberately do not enter it. */
110
+ val semanticGenerationIdentity: String by lazy {
111
+ sha256(
112
+ listOf(
113
+ source.kind,
114
+ source.value,
115
+ configuration.configJson,
116
+ configuration.themeJson.orEmpty(),
117
+ configuration.imagePolicyJson.orEmpty(),
118
+ if (configuration.imagesEnabled) "1" else "0",
119
+ if (configuration.collapsesWhenEmpty) "1" else "0",
120
+ mentionPrefix.orEmpty()
121
+ ).joinToString("\u001f")
122
+ )
123
+ }
124
+
125
+ /** Immutable layout/cache identity including permitted state-only revisions. */
126
+ val generationIdentity: String by lazy {
127
+ sha256(
128
+ listOf(
129
+ semanticGenerationIdentity,
130
+ attachmentRevision.toString(),
131
+ nativeFontRevision.toString(),
132
+ fontEnvironmentRevision.toString()
133
+ ).joinToString("\u001f")
134
+ )
135
+ }
136
+ val mentionPrefix: String? get() = mentionPrefix(configuration.configJson)
137
+ }
138
+
139
+ internal typealias DocumentCompiler = (ProseViewerRequest) -> ViewerDocument
140
+
141
+ internal fun compileWithRust(request: ProseViewerRequest): ViewerDocument {
142
+ val result = viewerCompile(
143
+ FfiViewerCompileRequest(
144
+ sourceKind = if (request.source is ProseViewerSource.Html) {
145
+ FfiViewerSourceKind.HTML
146
+ } else {
147
+ FfiViewerSourceKind.JSON
148
+ },
149
+ source = request.source.value,
150
+ configJson = request.configuration.configJson,
151
+ imagesEnabled = request.configuration.imagesEnabled,
152
+ mentionPrefix = request.mentionPrefix
153
+ )
154
+ )
155
+ try {
156
+ result.error?.let { throw ProseViewerError.compiler(it.domain, it.code, it.message) }
157
+ val compiled =
158
+ result.value
159
+ ?: throw ProseViewerError.compiler(
160
+ "viewer",
161
+ "MISSING_COMPILED_DOCUMENT",
162
+ "The compiler returned neither a document nor an error."
163
+ )
164
+ val semanticKey = compiled.semanticKey()
165
+ if (!semanticKey.matches(Regex("[0-9a-f]{64}"))) {
166
+ throw ProseViewerError.compiler(
167
+ "viewer",
168
+ "INVALID_SEMANTIC_KEY",
169
+ "The compiler returned an invalid semantic key."
170
+ )
171
+ }
172
+
173
+ data class Builder(
174
+ val nodeType: String,
175
+ val depth: Int,
176
+ val listContext: ViewerListContext?,
177
+ val listItemIdentity: Int?,
178
+ val listItemContext: ViewerListContext?,
179
+ val identity: Int,
180
+ val language: String? = null,
181
+ val inlines: MutableList<ViewerInline> = mutableListOf()
182
+ )
183
+
184
+ val stack = mutableListOf<Builder>()
185
+ val rendered = mutableListOf<ViewerBlock>()
186
+ // A list item's terminal spacing belongs after its own direct leaves,
187
+ // before a child list begins. Descendant leaves are retained only as a
188
+ // fallback for an item whose sole renderable content is nested.
189
+ val directLeavesByListItem = mutableMapOf<Int, MutableList<Int>>()
190
+ val descendantLeavesByListItem = mutableMapOf<Int, MutableList<Int>>()
191
+ val listItemDepths = mutableMapOf<Int, Int>()
192
+ var nextListItemIdentity = 0
193
+ var nextContainerIdentity = 0
194
+
195
+ fun nearestListContext(builders: List<Builder>): ViewerListContext? =
196
+ builders.asReversed().firstNotNullOfOrNull {
197
+ it.listContext
198
+ }
199
+ fun listItemAncestors(builders: List<Builder>): List<ViewerListItemAncestor> =
200
+ builders.mapNotNull { builder ->
201
+ val identity = builder.listItemIdentity ?: return@mapNotNull null
202
+ val context = builder.listItemContext ?: return@mapNotNull null
203
+ ViewerListItemAncestor(identity, context, builder.depth, false, false)
204
+ }
205
+ fun appendLeaf(
206
+ nodeType: String,
207
+ depth: Int,
208
+ inlines: List<ViewerInline>,
209
+ ancestors: List<Builder>,
210
+ isBlockAtom: Boolean = false
211
+ ) {
212
+ val itemAncestors = listItemAncestors(ancestors)
213
+ rendered += ViewerBlock(
214
+ nodeType = nodeType,
215
+ depth = depth,
216
+ inBlockquote = ancestors.any { it.nodeType == "blockquote" },
217
+ listContext = nearestListContext(ancestors),
218
+ listItemBoundary = null,
219
+ inlines = inlines,
220
+ isBlockAtom = isBlockAtom,
221
+ language = ancestors.lastOrNull()?.language,
222
+ containers = ancestors.filter {
223
+ it.nodeType in CONTAINER_BLOCKS &&
224
+ it.nodeType != "doc"
225
+ }.map { ViewerContainerAncestor(it.identity, it.nodeType, 0, 0) },
226
+ listItemAncestors = itemAncestors,
227
+ outermostListItemIdentity = itemAncestors.firstOrNull()?.identity,
228
+ outermostListItemIsLast = itemAncestors.firstOrNull()?.context?.isLast == true
229
+ )
230
+ itemAncestors.forEach { ancestor ->
231
+ descendantLeavesByListItem.getOrPut(ancestor.identity) { mutableListOf() } +=
232
+ rendered.lastIndex
233
+ }
234
+ itemAncestors.lastOrNull()?.let { nearest ->
235
+ directLeavesByListItem.getOrPut(nearest.identity) { mutableListOf() } +=
236
+ rendered.lastIndex
237
+ }
238
+ }
239
+
240
+ compiled.elements().forEach { element ->
241
+ when (element) {
242
+ is FfiViewerElement.BlockStart -> {
243
+ val context = listContext(element.listContextJson)
244
+ if (context?.isFirst == true) {
245
+ stack +=
246
+ Builder(
247
+ if (context.kind ==
248
+ "task"
249
+ ) {
250
+ "taskList"
251
+ } else if (context.ordered) {
252
+ "orderedList"
253
+ } else {
254
+ "bulletList"
255
+ },
256
+ element.depth.toInt(),
257
+ null,
258
+ null,
259
+ null,
260
+ nextContainerIdentity++
261
+ )
262
+ }
263
+ val identity = if (context != null) nextListItemIdentity++ else null
264
+ identity?.let { listItemDepths[it] = element.depth.toInt() }
265
+ stack += Builder(
266
+ element.nodeType,
267
+ element.depth.toInt(),
268
+ context,
269
+ identity,
270
+ if (identity == null) null else context,
271
+ nextContainerIdentity++,
272
+ element.language
273
+ )
274
+ }
275
+
276
+ is FfiViewerElement.TextRun -> stack.lastOrNull()?.inlines?.add(
277
+ ViewerInline.Text(element.text, element.marks)
278
+ )
279
+
280
+ is FfiViewerElement.InlineAtom -> stack.lastOrNull()?.inlines?.add(
281
+ ViewerInline.Atom(
282
+ element.nodeType,
283
+ u32(element.docPos),
284
+ element.attrsJson,
285
+ element.label
286
+ )
287
+ )
288
+
289
+ is FfiViewerElement.BlockAtom -> appendLeaf(
290
+ element.nodeType,
291
+ stack.lastOrNull()?.depth ?: 0,
292
+ listOf(
293
+ ViewerInline.Atom(
294
+ element.nodeType,
295
+ u32(element.docPos),
296
+ element.attrsJson,
297
+ element.label
298
+ )
299
+ ),
300
+ stack,
301
+ isBlockAtom = true
302
+ )
303
+
304
+ FfiViewerElement.BlockEnd -> {
305
+ val builder = stack.removeLastOrNull() ?: return@forEach
306
+ // Containers are represented by inherited context. Every text block,
307
+ // including an empty paragraph, remains a leaf for list boundaries.
308
+ if (builder.nodeType !in CONTAINER_BLOCKS && builder.listItemIdentity == null) {
309
+ appendLeaf(
310
+ builder.nodeType,
311
+ builder.depth,
312
+ builder.inlines,
313
+ stack + builder
314
+ )
315
+ }
316
+ if (builder.listItemContext?.isLast == true &&
317
+ stack.lastOrNull()?.nodeType in
318
+ setOf("bulletList", "orderedList", "taskList")
319
+ ) {
320
+ stack.removeLastOrNull()
321
+ }
322
+ }
323
+ }
324
+ }
325
+ descendantLeavesByListItem.forEach { (identity, descendantLeaves) ->
326
+ val leaves =
327
+ directLeavesByListItem[identity]?.takeIf { it.isNotEmpty() } ?: descendantLeaves
328
+ val first = leaves.firstOrNull() ?: return@forEach
329
+ val final = leaves.last()
330
+ leaves.forEach { index ->
331
+ val updatedAncestors = rendered[index].listItemAncestors.map { ancestor ->
332
+ if (ancestor.identity == identity) {
333
+ ancestor.copy(
334
+ nestingDepth = listItemDepths[identity] ?: ancestor.nestingDepth,
335
+ isFirstRenderableLeaf = index == first,
336
+ isFinalRenderableLeaf = index == final
337
+ )
338
+ } else {
339
+ ancestor
340
+ }
341
+ }
342
+ val nearest = updatedAncestors.lastOrNull()
343
+ rendered[index] = rendered[index].copy(
344
+ listItemBoundary = nearest?.let {
345
+ ViewerListItemBoundary(
346
+ it.identity,
347
+ it.nestingDepth,
348
+ it.isFirstRenderableLeaf,
349
+ it.isFinalRenderableLeaf
350
+ )
351
+ },
352
+ listItemAncestors = updatedAncestors
353
+ )
354
+ }
355
+ }
356
+ val containerLeaves = mutableMapOf<Int, MutableList<Int>>()
357
+ rendered.forEachIndexed { index, block ->
358
+ block.containers.forEach {
359
+ containerLeaves.getOrPut(it.identity) { mutableListOf() } +=
360
+ index
361
+ }
362
+ }
363
+ rendered.indices.forEach { index ->
364
+ rendered[index] = rendered[index].copy(
365
+ containers = rendered[index].containers.map {
366
+ val leaves = containerLeaves.getValue(it.identity)
367
+ it.copy(firstLeaf = leaves.first(), lastLeaf = leaves.last())
368
+ }
369
+ )
370
+ }
371
+ val fallback = if (rendered.isEmpty() &&
372
+ !compiled.isEmpty()
373
+ ) {
374
+ listOf(ViewerBlock("paragraph", 0, false, null, null, emptyList()))
375
+ } else {
376
+ rendered
377
+ }
378
+ val admittedAttachmentCount = fallback.count { block ->
379
+ block.nodeType == "image" && ViewerImageAttachment.sourceAndDeclaredSize(block) != null
380
+ }
381
+ if (admittedAttachmentCount > ViewerImageAttachment.MAXIMUM_ADMITTED_ATTACHMENTS) {
382
+ throw ProseViewerError.compiler(
383
+ "viewer",
384
+ "ATTACHMENT_LIMIT_EXCEEDED",
385
+ "The document exceeds the maximum admitted image attachment count."
386
+ )
387
+ }
388
+ return ViewerDocument(
389
+ semanticKey = semanticKey,
390
+ blocks = fallback,
391
+ isEmpty = compiled.isEmpty(),
392
+ retainedBytes = compiled.retainedBytesDecimal().toLongOrNull() ?: 0,
393
+ trailingEmptyTextBlockCount = compiled.trailingEmptyTextBlockCount().toInt()
394
+ )
395
+ } finally {
396
+ result.destroy()
397
+ }
398
+ }
399
+
400
+ private val CONTAINER_BLOCKS = setOf(
401
+ "doc",
402
+ "blockquote",
403
+ "bulletList",
404
+ "bullet_list",
405
+ "orderedList",
406
+ "ordered_list",
407
+ "taskList",
408
+ "task_list",
409
+ "listItem",
410
+ "list_item",
411
+ "taskItem",
412
+ "task_item"
413
+ )
414
+
415
+ internal fun listContext(json: String?): ViewerListContext? = runCatching {
416
+ json ?: return@runCatching null
417
+ val value = JSONObject(json)
418
+ val index = if (value.has("index")) u32(value.opt("index")) else 1L
419
+ ViewerListContext(
420
+ value.optBoolean("ordered"),
421
+ index,
422
+ value.optionalString("kind"),
423
+ value.optBoolean("checked"),
424
+ value.optBoolean("isLast"),
425
+ value.optBoolean("isFirst")
426
+ )
427
+ }.getOrNull()
428
+
429
+ /**
430
+ * `optString(key, null)` cannot express an absent value: its fallback is
431
+ * declared non-null, and a present JSON null coerces to the string "null".
432
+ */
433
+ internal fun JSONObject.optionalString(key: String): String? =
434
+ if (isNull(key)) null else optString(key)
435
+
436
+ /** JSON and UniFFI may expose Rust u32 values through different Kotlin number types. */
437
+ private fun u32(value: Any?): Long {
438
+ val parsed = value?.toString()?.toLongOrNull()
439
+ ?: throw IllegalArgumentException("Expected an unsigned 32-bit semantic value.")
440
+ require(parsed in 0L..0xFFFF_FFFFL) { "Semantic value is outside Rust u32 range." }
441
+ return parsed
442
+ }
443
+
444
+ private fun mentionPrefix(configJson: String): String? = runCatching {
445
+ val root = JSONObject(configJson)
446
+ root.optJSONObject("mentions")?.optionalString("prefix") ?: root.optionalString("mentionPrefix")
447
+ }.getOrNull()
448
+
449
+ internal fun sha256(value: String): String = MessageDigest.getInstance(
450
+ "SHA-256"
451
+ ).digest(value.toByteArray(Charsets.UTF_8)).joinToString("") {
452
+ "%02x".format(it)
453
+ }