@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,313 @@
1
+ import CryptoKit
2
+ import ImageIO
3
+ import UIKit
4
+
5
+ extension RenderBridge {
6
+ static func attributedStringApplyingLeadingTopLevelChildIndexIfNeeded(
7
+ _ attributedString: NSAttributedString,
8
+ topLevelChildIndex: Int?,
9
+ resultIsEmpty: Bool
10
+ ) -> NSAttributedString {
11
+ guard resultIsEmpty,
12
+ let topLevelChildIndex,
13
+ attributedString.length > 0
14
+ else {
15
+ return attributedString
16
+ }
17
+
18
+ let tagged = NSMutableAttributedString(attributedString: attributedString)
19
+ let firstComposedCharacterRange = (tagged.string as NSString)
20
+ .rangeOfComposedCharacterSequence(at: 0)
21
+ tagged.addAttribute(
22
+ RenderBridgeAttributes.topLevelChildIndex,
23
+ value: NSNumber(value: topLevelChildIndex),
24
+ range: firstComposedCharacterRange
25
+ )
26
+ return tagged
27
+ }
28
+
29
+ static func removingLeadingTopLevelChildIndex(
30
+ from attributedString: NSAttributedString,
31
+ topLevelChildIndex: Int
32
+ ) -> NSAttributedString {
33
+ guard attributedString.length > 0 else { return attributedString }
34
+
35
+ let firstValue = attributedString.attribute(
36
+ RenderBridgeAttributes.topLevelChildIndex,
37
+ at: 0,
38
+ effectiveRange: nil
39
+ ) as? NSNumber
40
+ guard firstValue?.intValue == topLevelChildIndex else {
41
+ return attributedString
42
+ }
43
+
44
+ let adjusted = NSMutableAttributedString(attributedString: attributedString)
45
+ var effectiveRange = NSRange(location: 0, length: 0)
46
+ adjusted.attribute(
47
+ RenderBridgeAttributes.topLevelChildIndex,
48
+ at: 0,
49
+ longestEffectiveRange: &effectiveRange,
50
+ in: NSRange(location: 0, length: adjusted.length)
51
+ )
52
+ adjusted.removeAttribute(
53
+ RenderBridgeAttributes.topLevelChildIndex,
54
+ range: effectiveRange
55
+ )
56
+ return adjusted
57
+ }
58
+
59
+ static func effectiveBlockContext(_ blockStack: [BlockContext]) -> BlockContext? {
60
+ guard let currentBlock = blockStack.last else { return nil }
61
+ if currentBlock.listContext != nil {
62
+ return currentBlock
63
+ }
64
+ guard let inheritedListBlock = nearestListBlock(in: Array(blockStack.dropLast())) else {
65
+ return currentBlock
66
+ }
67
+ return BlockContext(
68
+ nodeType: currentBlock.nodeType,
69
+ depth: currentBlock.depth,
70
+ listContext: inheritedListBlock.listContext,
71
+ listMarkerContext: currentBlock.listMarkerContext,
72
+ markerPending: false
73
+ )
74
+ }
75
+
76
+ private static func nearestListBlock(in contexts: [BlockContext]) -> BlockContext? {
77
+ for context in contexts.reversed() where context.listContext != nil {
78
+ return context
79
+ }
80
+ return nil
81
+ }
82
+
83
+ static func trailingRenderedContentHasBlockquote(
84
+ in result: NSAttributedString
85
+ ) -> Bool {
86
+ guard result.length > 0 else { return false }
87
+ let nsString = result.string as NSString
88
+
89
+ for index in stride(from: result.length - 1, through: 0, by: -1) {
90
+ let scalar = nsString.character(at: index)
91
+ if scalar == 0x000A || scalar == 0x000D {
92
+ continue
93
+ }
94
+ return result.attribute(
95
+ RenderBridgeAttributes.blockquoteBorderColor,
96
+ at: index,
97
+ effectiveRange: nil
98
+ ) != nil
99
+ }
100
+
101
+ return false
102
+ }
103
+
104
+ static func consumePendingListMarker(from blockStack: inout [BlockContext]) -> [String: Any]? {
105
+ guard blockStack.count >= 2 else { return nil }
106
+ for idx in stride(from: blockStack.count - 2, through: 0, by: -1) {
107
+ guard blockStack[idx].markerPending else { continue }
108
+ blockStack[idx].markerPending = false
109
+ return blockStack[idx].listContext
110
+ }
111
+ return nil
112
+ }
113
+
114
+ static func isListItemNodeType(_ nodeType: String) -> Bool {
115
+ EditorNodeTypes.isListItem(nodeType)
116
+ }
117
+
118
+ static func overrideTrailingParagraphSpacing(
119
+ in result: NSMutableAttributedString,
120
+ paragraphSpacing: CGFloat
121
+ ) {
122
+ guard result.length > 0 else { return }
123
+
124
+ let nsString = result.string as NSString
125
+ let paragraphRange = nsString.paragraphRange(for: NSRange(location: result.length - 1, length: 0))
126
+ result.enumerateAttribute(
127
+ .paragraphStyle,
128
+ in: paragraphRange,
129
+ options: [.longestEffectiveRangeNotRequired]
130
+ ) { value, range, _ in
131
+ let sourceStyle = (value as? NSParagraphStyle)?.mutableCopy() as? NSMutableParagraphStyle
132
+ ?? NSMutableParagraphStyle()
133
+ sourceStyle.paragraphSpacing = paragraphSpacing
134
+ result.addAttribute(.paragraphStyle, value: sourceStyle, range: range)
135
+ }
136
+ }
137
+
138
+ static func collapseTrailingSpacingBeforeHorizontalRuleIfNeeded(
139
+ in result: NSMutableAttributedString,
140
+ pendingParagraphSpacing: inout CGFloat?,
141
+ nodeType: String,
142
+ theme: EditorTheme?
143
+ ) {
144
+ guard EditorNodeTypes.isHorizontalRule(nodeType) else { return }
145
+ let horizontalRuleMargin = resolvedHorizontalRuleVerticalMargin(theme: theme)
146
+
147
+ if let pendingSpacing = pendingParagraphSpacing {
148
+ pendingParagraphSpacing = collapsedSpacing(
149
+ existingSpacing: pendingSpacing,
150
+ adjacentHorizontalRuleMargin: horizontalRuleMargin
151
+ )
152
+ return
153
+ }
154
+
155
+ guard let trailingParagraphSpacing = trailingParagraphSpacing(in: result) else { return }
156
+ let adjustedSpacing = collapsedSpacing(
157
+ existingSpacing: trailingParagraphSpacing,
158
+ adjacentHorizontalRuleMargin: horizontalRuleMargin
159
+ )
160
+ guard abs(adjustedSpacing - trailingParagraphSpacing) > 0.01 else { return }
161
+ overrideTrailingParagraphSpacing(in: result, paragraphSpacing: adjustedSpacing)
162
+ }
163
+
164
+ static func collapsedParagraphSpacingAfterHorizontalRule(
165
+ in result: NSAttributedString,
166
+ separatorBlockStack: [BlockContext],
167
+ theme: EditorTheme?,
168
+ baseFont: UIFont
169
+ ) -> CGFloat? {
170
+ guard let horizontalRuleMargin = trailingHorizontalRuleMargin(in: result),
171
+ let separatorSpacing = separatorParagraphSpacing(
172
+ for: separatorBlockStack,
173
+ theme: theme,
174
+ baseFont: baseFont
175
+ )
176
+ else {
177
+ return nil
178
+ }
179
+
180
+ return collapsedSpacing(
181
+ existingSpacing: separatorSpacing,
182
+ adjacentHorizontalRuleMargin: horizontalRuleMargin
183
+ )
184
+ }
185
+
186
+ @discardableResult
187
+ static func applyPendingTrailingParagraphSpacing(
188
+ in result: NSMutableAttributedString,
189
+ pendingParagraphSpacing: inout CGFloat?
190
+ ) -> Bool {
191
+ guard let paragraphSpacing = pendingParagraphSpacing else { return false }
192
+ overrideTrailingParagraphSpacing(in: result, paragraphSpacing: paragraphSpacing)
193
+ pendingParagraphSpacing = nil
194
+ return true
195
+ }
196
+
197
+ private static func trailingParagraphSpacing(in result: NSAttributedString) -> CGFloat? {
198
+ guard result.length > 0 else { return nil }
199
+
200
+ let nsString = result.string as NSString
201
+ let paragraphRange = nsString.paragraphRange(for: NSRange(location: result.length - 1, length: 0))
202
+ var spacing: CGFloat?
203
+ result.enumerateAttribute(
204
+ .paragraphStyle,
205
+ in: paragraphRange,
206
+ options: [.reverse, .longestEffectiveRangeNotRequired]
207
+ ) { value, _, stop in
208
+ if let paragraphStyle = value as? NSParagraphStyle {
209
+ spacing = paragraphStyle.paragraphSpacing
210
+ stop.pointee = true
211
+ }
212
+ }
213
+ return spacing
214
+ }
215
+
216
+ private static func separatorParagraphSpacing(
217
+ for blockStack: [BlockContext],
218
+ theme: EditorTheme?,
219
+ baseFont: UIFont
220
+ ) -> CGFloat? {
221
+ guard let currentBlock = effectiveBlockContext(blockStack) else { return nil }
222
+ return paragraphStyleForBlock(
223
+ currentBlock,
224
+ blockStack: blockStack,
225
+ theme: theme,
226
+ baseFont: baseFont
227
+ ).paragraphSpacing
228
+ }
229
+
230
+ private static func trailingHorizontalRuleMargin(in result: NSAttributedString) -> CGFloat? {
231
+ guard result.length > 0 else { return nil }
232
+ let nsString = result.string as NSString
233
+
234
+ for index in stride(from: result.length - 1, through: 0, by: -1) {
235
+ let scalar = nsString.character(at: index)
236
+ if scalar == 0x000A || scalar == 0x000D {
237
+ continue
238
+ }
239
+ guard let nodeType = result.attribute(
240
+ RenderBridgeAttributes.voidNodeType,
241
+ at: index,
242
+ effectiveRange: nil
243
+ ) as? String, EditorNodeTypes.isHorizontalRule(nodeType) else {
244
+ return nil
245
+ }
246
+ return (
247
+ result.attribute(.attachment, at: index, effectiveRange: nil)
248
+ as? HorizontalRuleAttachment
249
+ )?.verticalPadding
250
+ }
251
+
252
+ return nil
253
+ }
254
+
255
+ static func resolvedHorizontalRuleVerticalMargin(theme: EditorTheme?) -> CGFloat {
256
+ theme?.horizontalRule?.verticalMargin ?? LayoutConstants.horizontalRuleVerticalPadding
257
+ }
258
+
259
+ private static func collapsedSpacing(
260
+ existingSpacing: CGFloat,
261
+ adjacentHorizontalRuleMargin: CGFloat
262
+ ) -> CGFloat {
263
+ max(existingSpacing, adjacentHorizontalRuleMargin) - adjacentHorizontalRuleMargin
264
+ }
265
+
266
+ static func appendTrailingLineBreakPlaceholderIfNeeded(
267
+ in result: NSMutableAttributedString,
268
+ endedBlock: BlockContext,
269
+ remainingBlockStack: [BlockContext],
270
+ baseFont: UIFont,
271
+ textColor: UIColor,
272
+ theme: EditorTheme?
273
+ ) {
274
+ guard result.length > 0 else { return }
275
+ guard !isListItemNodeType(endedBlock.nodeType) else { return }
276
+ let nodeType = result.attribute(
277
+ RenderBridgeAttributes.voidNodeType,
278
+ at: result.length - 1,
279
+ effectiveRange: nil
280
+ ) as? String
281
+ let isHardBreak = nodeType.map(EditorNodeTypes.isHardBreak) ?? false
282
+ let isCodeNewline = EditorStyleSheet.element(endedBlock.nodeType) == "codeBlock"
283
+ && (result.string as NSString).character(at: result.length - 1) == 0x000A
284
+ guard isHardBreak || isCodeNewline else { return }
285
+
286
+ let placeholderBlockStack = remainingBlockStack + [endedBlock]
287
+ let blockFont = resolvedFont(
288
+ for: placeholderBlockStack,
289
+ baseFont: baseFont,
290
+ theme: theme
291
+ )
292
+ let blockColor = resolvedTextColor(
293
+ for: placeholderBlockStack,
294
+ textColor: textColor,
295
+ theme: theme
296
+ )
297
+ var attrs = defaultAttributes(baseFont: blockFont, textColor: blockColor)
298
+ attrs[RenderBridgeAttributes.syntheticPlaceholder] = true
299
+ var styledAttrs = applyBlockStyle(
300
+ to: attrs,
301
+ blockStack: placeholderBlockStack,
302
+ theme: theme,
303
+ blockBaseFont: blockFont
304
+ )
305
+ if let paragraphStyle = (styledAttrs[.paragraphStyle] as? NSParagraphStyle)?.mutableCopy()
306
+ as? NSMutableParagraphStyle {
307
+ paragraphStyle.paragraphSpacing = 0
308
+ styledAttrs[.paragraphStyle] = paragraphStyle
309
+ }
310
+ result.append(NSAttributedString(string: "\u{200B}", attributes: styledAttrs))
311
+ }
312
+
313
+ }
@@ -0,0 +1,343 @@
1
+ import CryptoKit
2
+ import ImageIO
3
+ import UIKit
4
+
5
+ extension RenderBridge {
6
+ /// Create a paragraph style for a block context.
7
+ ///
8
+ /// Applies indentation based on depth and list context. List items get
9
+ /// a hanging indent so the bullet/number sits in the margin.
10
+ static func paragraphStyleForBlock(
11
+ _ context: BlockContext,
12
+ blockStack: [BlockContext],
13
+ theme: EditorTheme? = nil,
14
+ baseFont: UIFont = .systemFont(ofSize: 16)
15
+ ) -> NSMutableParagraphStyle {
16
+ let style = NSMutableParagraphStyle()
17
+ if let sheet = theme?.styleSheet {
18
+ let ancestors = blockStack.dropLast().map(\.nodeType)
19
+ let text = sheet.textStyle(context.nodeType, ancestors: ancestors)
20
+ let horizontal = blockStack.reduce(UIEdgeInsets.zero) { $0.adding(sheet.box($1.nodeType).outerInsets) }
21
+ let listName = context.listContext.map { ($0["kind"] as? String) == "task" ? "taskList" : (($0["ordered"] as? NSNumber)?.boolValue == true ? "orderedList" : "bulletList") }
22
+ let list = listName.map { sheet[$0] } ?? [:]
23
+ let indent = EditorTheme.cgFloat(list["indent"]) ?? LayoutConstants.indentPerDepth
24
+ let multiplier = EditorTheme.cgFloat(list["baseIndentMultiplier"]) ?? 1
25
+ let listDepth = max(0, blockStack.filter { $0.listContext != nil }.count - 1)
26
+ let listInset = listName == nil ? 0 : indent * (CGFloat(listDepth) + multiplier) + listMarkerWidth(for: context, theme: theme, baseFont: baseFont)
27
+ style.headIndent = horizontal.left + listInset
28
+ style.firstLineHeadIndent = style.headIndent
29
+ style.tailIndent = -horizontal.right
30
+ if let height = text.lineHeight { style.minimumLineHeight = height; style.maximumLineHeight = height }
31
+ let values = sheet.textValues(context.nodeType, ancestors: ancestors)
32
+ switch values["textAlign"] as? String {
33
+ case "center": style.alignment = .center
34
+ case "right": style.alignment = .right
35
+ case "justify": style.alignment = .justified
36
+ default: break
37
+ }
38
+ return style
39
+ }
40
+
41
+ let blockStyle = theme?.effectiveTextStyle(
42
+ for: context.nodeType,
43
+ inBlockquote: blockquoteDepth(in: blockStack) > 0
44
+ )
45
+ let spacing = blockStyle?.spacingAfter
46
+ ?? (context.listContext != nil ? theme?.list?.itemSpacing : nil)
47
+ ?? LayoutConstants.paragraphSpacing
48
+ style.paragraphSpacing = spacing
49
+
50
+ let indentPerDepth = theme?.list?.indent ?? LayoutConstants.indentPerDepth
51
+ let markerWidth = listMarkerWidth(for: context, theme: theme, baseFont: baseFont)
52
+ let quoteDepth = CGFloat(blockquoteDepth(in: blockStack))
53
+ let quoteIndent = max(
54
+ theme?.blockquote?.indent ?? LayoutConstants.blockquoteIndent,
55
+ (theme?.blockquote?.markerGap ?? LayoutConstants.blockquoteMarkerGap)
56
+ + (theme?.blockquote?.borderWidth ?? LayoutConstants.blockquoteBorderWidth)
57
+ )
58
+ let listBaseIndentMultiplier = max(theme?.list?.baseIndentMultiplier ?? 1, 0)
59
+ let listBaseIndentAdjustment = context.listContext != nil
60
+ ? ((listBaseIndentMultiplier - 1) * indentPerDepth)
61
+ : 0
62
+ let columnsDepth = CGFloat(columnContainerDepth(in: blockStack))
63
+ let baseIndent = (CGFloat(context.depth) * indentPerDepth)
64
+ - (quoteDepth * indentPerDepth)
65
+ - (columnsDepth * indentPerDepth)
66
+ + listBaseIndentAdjustment
67
+ + (quoteDepth * quoteIndent)
68
+
69
+ if context.listContext != nil {
70
+ // List item: reserve a fixed gutter and align all wrapped lines to
71
+ // the text start since the marker is drawn separately.
72
+ style.firstLineHeadIndent = baseIndent + markerWidth
73
+ style.headIndent = baseIndent + markerWidth
74
+ } else {
75
+ style.firstLineHeadIndent = baseIndent
76
+ style.headIndent = baseIndent
77
+ }
78
+
79
+ if context.nodeType == "codeBlock" {
80
+ let horizontalPadding = theme?.codeBlock?.paddingHorizontal ?? 12
81
+ style.firstLineHeadIndent += horizontalPadding
82
+ style.headIndent += horizontalPadding
83
+ style.tailIndent = -horizontalPadding
84
+ }
85
+
86
+ if let lineHeight = blockStyle?.lineHeight {
87
+ style.minimumLineHeight = lineHeight
88
+ style.maximumLineHeight = lineHeight
89
+ }
90
+
91
+ return style
92
+ }
93
+
94
+ /// Generate the list marker string (bullet or number) from a list context.
95
+ static func listMarkerString(listContext: [String: Any]) -> String {
96
+ if (listContext["kind"] as? String) == "task" {
97
+ let checked = (listContext["checked"] as? NSNumber)?.boolValue ?? false
98
+ return checked ? "\u{2611} " : "\u{2610} "
99
+ }
100
+ let ordered = (listContext["ordered"] as? NSNumber)?.boolValue ?? false
101
+
102
+ if ordered {
103
+ guard let rawIndex = listContext["index"] else { return "1. " }
104
+ guard let index = v2ExactUInt32(rawIndex as? NSNumber) else { return "" }
105
+ return "\(index). "
106
+ } else {
107
+ return LayoutConstants.unorderedListBullet
108
+ }
109
+ }
110
+
111
+ /// Extract a `UInt32` from a JSON value produced by `JSONSerialization`.
112
+ static func jsonUInt32(_ value: Any?) -> UInt32? {
113
+ v2ExactUInt32(value as? NSNumber)
114
+ }
115
+
116
+ /// Extract a `UInt8` from a JSON value produced by `JSONSerialization`.
117
+ static func jsonUInt8(_ value: Any?) -> UInt8 {
118
+ if let number = value as? NSNumber {
119
+ return number.uint8Value
120
+ }
121
+ return 0
122
+ }
123
+
124
+ static func jsonInt(_ value: Any?) -> Int? {
125
+ if let number = value as? NSNumber {
126
+ return number.intValue
127
+ }
128
+ if let string = value as? String,
129
+ let resolved = Int(string.trimmingCharacters(in: .whitespacesAndNewlines)) {
130
+ return resolved
131
+ }
132
+ return nil
133
+ }
134
+
135
+ /// Extract a positive `CGFloat` from a JSON value produced by `JSONSerialization`.
136
+ static func jsonCGFloat(_ value: Any?) -> CGFloat? {
137
+ if let number = value as? NSNumber {
138
+ let resolved = CGFloat(truncating: number)
139
+ return resolved > 0 ? resolved : nil
140
+ }
141
+ if let string = value as? String,
142
+ let resolved = Double(string.trimmingCharacters(in: .whitespacesAndNewlines)),
143
+ resolved > 0 {
144
+ return CGFloat(resolved)
145
+ }
146
+ return nil
147
+ }
148
+
149
+ static func defaultAttributes(
150
+ baseFont: UIFont,
151
+ textColor: UIColor
152
+ ) -> [NSAttributedString.Key: Any] {
153
+ [
154
+ .font: baseFont,
155
+ .foregroundColor: textColor
156
+ ]
157
+ }
158
+
159
+ @discardableResult
160
+ static func applyBlockStyle(
161
+ to attrs: [NSAttributedString.Key: Any],
162
+ blockStack: [BlockContext],
163
+ theme: EditorTheme?,
164
+ blockBaseFont: UIFont? = nil
165
+ ) -> [NSAttributedString.Key: Any] {
166
+ guard let currentBlock = effectiveBlockContext(blockStack) else { return attrs }
167
+ var mutableAttrs = attrs
168
+ if theme?.styleSheet != nil { mutableAttrs[editorStyledContentAttribute] = true }
169
+ let renderedFont = mutableAttrs[.font] as? UIFont ?? .systemFont(ofSize: 16)
170
+ let paragraphBaseFont = blockBaseFont ?? renderedFont
171
+ mutableAttrs[.paragraphStyle] = paragraphStyleForBlock(
172
+ currentBlock,
173
+ blockStack: blockStack,
174
+ theme: theme,
175
+ baseFont: paragraphBaseFont
176
+ )
177
+ mutableAttrs[RenderBridgeAttributes.blockNodeType] = currentBlock.nodeType
178
+ mutableAttrs[RenderBridgeAttributes.blockDepth] = currentBlock.depth
179
+ if let listContext = currentBlock.listContext {
180
+ mutableAttrs[RenderBridgeAttributes.listContext] = listContext
181
+ }
182
+ if let markerContext = currentBlock.listMarkerContext {
183
+ mutableAttrs[RenderBridgeAttributes.listMarkerContext] = markerContext
184
+ let visualListDepth = max(0, blockStack.filter { $0.listContext != nil }.count - 1)
185
+ if (markerContext["kind"] as? String) != "task",
186
+ (markerContext["ordered"] as? NSNumber)?.boolValue == true,
187
+ let rawIndex = markerContext["index"] as? NSNumber,
188
+ let index = v2ExactUInt32(rawIndex) {
189
+ mutableAttrs[RenderBridgeAttributes.orderedListMarkerLabel] =
190
+ OrderedListMarkerFormatter.label(
191
+ index: index,
192
+ nestingDepth: visualListDepth,
193
+ theme: theme?.list?.orderedMarker
194
+ )
195
+ }
196
+ mutableAttrs[RenderBridgeAttributes.listMarkerColor] = theme?.list?.markerColor
197
+ mutableAttrs[RenderBridgeAttributes.listMarkerScale] = theme?.list?.markerScale
198
+ if let sheet = theme?.styleSheet {
199
+ mutableAttrs[RenderBridgeAttributes.listMarkerScale] = EditorTheme.cgFloat(sheet["listMarker"]["scale"]) ?? ((markerContext["ordered"] as? Bool) == true ? 1 : LayoutConstants.unorderedListMarkerFontScale)
200
+ }
201
+ mutableAttrs[RenderBridgeAttributes.listMarkerGap] = theme?.list?.markerGap
202
+ mutableAttrs[RenderBridgeAttributes.listMarkerBaseFont] = paragraphBaseFont
203
+ if let sheet = theme?.styleSheet, (markerContext["kind"] as? String) == "task" {
204
+ let checkbox = sheet.checkbox(checked: markerContext["checked"] as? Bool == true)
205
+ mutableAttrs[editorTaskCheckboxAttribute] = EditorMentionRenderedBox(box: checkbox)
206
+ mutableAttrs[RenderBridgeAttributes.listMarkerGap] = checkbox.number("gap", fallback: 8)
207
+ }
208
+ mutableAttrs[RenderBridgeAttributes.listMarkerWidth] = listMarkerWidth(
209
+ for: currentBlock,
210
+ theme: theme,
211
+ baseFont: paragraphBaseFont
212
+ )
213
+ }
214
+ if currentBlock.nodeType == "codeBlock", theme?.styleSheet == nil {
215
+ mutableAttrs[RenderBridgeAttributes.codeBlockBackgroundColor] =
216
+ theme?.codeBlock?.backgroundColor ?? UIColor.secondarySystemBackground
217
+ mutableAttrs[RenderBridgeAttributes.codeBlockBorderRadius] =
218
+ theme?.codeBlock?.borderRadius ?? 8
219
+ mutableAttrs[RenderBridgeAttributes.codeBlockPaddingHorizontal] =
220
+ theme?.codeBlock?.paddingHorizontal ?? 12
221
+ mutableAttrs[RenderBridgeAttributes.codeBlockPaddingVertical] =
222
+ theme?.codeBlock?.paddingVertical ?? 8
223
+ }
224
+ if blockquoteDepth(in: blockStack) > 0, theme?.styleSheet == nil {
225
+ let foreground = mutableAttrs[.foregroundColor] as? UIColor ?? .separator
226
+ mutableAttrs[RenderBridgeAttributes.blockquoteBorderColor] =
227
+ theme?.blockquote?.borderColor
228
+ ?? foreground.withAlphaComponent(0.3)
229
+ mutableAttrs[RenderBridgeAttributes.blockquoteBorderWidth] =
230
+ theme?.blockquote?.borderWidth ?? LayoutConstants.blockquoteBorderWidth
231
+ mutableAttrs[RenderBridgeAttributes.blockquoteMarkerGap] =
232
+ theme?.blockquote?.markerGap ?? LayoutConstants.blockquoteMarkerGap
233
+ }
234
+ return mutableAttrs
235
+ }
236
+
237
+ /// Create a newline attributed string used between blocks.
238
+ ///
239
+ /// This newline separates consecutive blocks in the flat rendered text.
240
+ static func interBlockNewline(
241
+ baseFont: UIFont,
242
+ textColor: UIColor,
243
+ blockStack: [BlockContext],
244
+ theme: EditorTheme?,
245
+ paragraphSpacingOverride: CGFloat? = nil,
246
+ topLevelChildIndex: Int? = nil
247
+ ) -> NSAttributedString {
248
+ var attrs = applyBlockStyle(
249
+ to: defaultAttributes(baseFont: baseFont, textColor: textColor),
250
+ blockStack: blockStack,
251
+ theme: theme,
252
+ blockBaseFont: baseFont
253
+ )
254
+ if let topLevelChildIndex {
255
+ attrs[RenderBridgeAttributes.topLevelChildIndex] = NSNumber(value: topLevelChildIndex)
256
+ }
257
+ attrs[RenderBridgeAttributes.blockBoundary] = true
258
+ if let paragraphSpacingOverride,
259
+ let paragraphStyle = (attrs[.paragraphStyle] as? NSParagraphStyle)?.mutableCopy()
260
+ as? NSMutableParagraphStyle {
261
+ paragraphStyle.paragraphSpacing = paragraphSpacingOverride
262
+ attrs[.paragraphStyle] = paragraphStyle
263
+ }
264
+ return NSAttributedString(string: "\n", attributes: attrs)
265
+ }
266
+
267
+ static func listMarkerWidth(
268
+ for context: BlockContext,
269
+ theme: EditorTheme?,
270
+ baseFont: UIFont
271
+ ) -> CGFloat {
272
+ guard let listContext = context.listContext else { return 0 }
273
+ if let sheet = theme?.styleSheet {
274
+ if (listContext["kind"] as? String) == "task" {
275
+ let box = sheet.checkbox(checked: listContext["checked"] as? Bool == true)
276
+ return box.number("size", fallback: 24) + box.number("gap", fallback: 8)
277
+ }
278
+ let ordered = (listContext["ordered"] as? Bool) == true
279
+ let scale = EditorTheme.cgFloat(sheet["listMarker"]["scale"]) ?? (ordered ? 1 : LayoutConstants.unorderedListMarkerFontScale)
280
+ let gap = EditorTheme.cgFloat(sheet["listMarker"]["gap"]) ?? 8
281
+ if !ordered {
282
+ return EditorLayoutManager.unorderedBulletDrawingRect(usedRect: .zero, lineFragmentRect: .zero, markerWidth: 0, baselineY: 0, baseFont: baseFont, markerScale: scale, origin: .zero).width + gap
283
+ }
284
+ let label = ordered
285
+ ? OrderedListMarkerFormatter.label(index: jsonUInt32(listContext["index"]) ?? 1, nestingDepth: Int(context.depth), theme: theme?.list?.orderedMarker)
286
+ : "•"
287
+ return ceil((label as NSString).size(withAttributes: [.font: baseFont.withSize(baseFont.pointSize * scale)]).width) + gap
288
+ }
289
+ return LayoutConstants.listMarkerWidth
290
+ }
291
+
292
+ private static func resolvedTextStyle(
293
+ for blockStack: [BlockContext],
294
+ theme: EditorTheme?
295
+ ) -> EditorTextStyle? {
296
+ if let sheet = theme?.styleSheet {
297
+ return sheet.textStyle(blockStack.last?.nodeType ?? "paragraph", ancestors: blockStack.dropLast().map(\.nodeType))
298
+ }
299
+ let inBlockquote = blockquoteDepth(in: blockStack) > 0
300
+ guard let currentBlock = effectiveBlockContext(blockStack) else {
301
+ return theme?.effectiveTextStyle(for: "paragraph", inBlockquote: inBlockquote)
302
+ }
303
+ return theme?.effectiveTextStyle(for: currentBlock.nodeType, inBlockquote: inBlockquote)
304
+ }
305
+
306
+ static func blockquoteDepth(in blockStack: [BlockContext]) -> Int {
307
+ blockStack.reduce(into: 0) { count, context in
308
+ if context.nodeType == "blockquote" {
309
+ count += 1
310
+ }
311
+ }
312
+ }
313
+
314
+ private static func columnContainerDepth(in blockStack: [BlockContext]) -> Int {
315
+ blockStack.reduce(into: 0) { count, context in
316
+ if context.nodeType == "columns" || context.nodeType == "column" {
317
+ count += 1
318
+ }
319
+ }
320
+ }
321
+
322
+ static func isTransparentContainer(_ nodeType: String) -> Bool {
323
+ nodeType == "blockquote" || nodeType == "columns" || nodeType == "column" || ["bulletList", "orderedList", "taskList"].contains(EditorStyleSheet.element(nodeType))
324
+ }
325
+
326
+ static func resolvedFont(
327
+ for blockStack: [BlockContext],
328
+ baseFont: UIFont,
329
+ theme: EditorTheme?
330
+ ) -> UIFont {
331
+ resolvedTextStyle(for: blockStack, theme: theme)?.resolvedFont(fallback: baseFont)
332
+ ?? baseFont
333
+ }
334
+
335
+ static func resolvedTextColor(
336
+ for blockStack: [BlockContext],
337
+ textColor: UIColor,
338
+ theme: EditorTheme?
339
+ ) -> UIColor {
340
+ resolvedTextStyle(for: blockStack, theme: theme)?.color ?? textColor
341
+ }
342
+
343
+ }