@mathers101/react-native-render-rich-text 0.1.9 → 0.1.14
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +20 -20
- package/README.md +140 -140
- package/ReactNativeRenderRichText.podspec +23 -23
- package/android/build.gradle +86 -86
- package/android/consumer-rules.pro +3 -3
- package/android/src/main/AndroidManifest.xml +2 -2
- package/android/src/main/java/com/renderrichtext/EnrichedTiptapTextLayoutManager.kt +24 -24
- package/android/src/main/java/com/renderrichtext/EnrichedTiptapTextPackage.kt +13 -13
- package/android/src/main/java/com/renderrichtext/MeasurementStore.kt +644 -644
- package/android/src/main/java/com/renderrichtext/accessibility/AccessibilityLabels.kt +17 -17
- package/android/src/main/java/com/renderrichtext/accessibility/AccessibleTiptapTextView.kt +112 -112
- package/android/src/main/java/com/renderrichtext/accessibility/TiptapAccessibilityHelper.kt +576 -576
- package/android/src/main/java/com/renderrichtext/events/CodeBlockPressEvent.kt +24 -24
- package/android/src/main/java/com/renderrichtext/events/ContextMenuItemPressEvent.kt +28 -28
- package/android/src/main/java/com/renderrichtext/events/CopyPressEvent.kt +24 -24
- package/android/src/main/java/com/renderrichtext/events/ImagePressEvent.kt +25 -25
- package/android/src/main/java/com/renderrichtext/events/LatexErrorEvent.kt +29 -29
- package/android/src/main/java/com/renderrichtext/events/LinkLongPressEvent.kt +23 -23
- package/android/src/main/java/com/renderrichtext/events/LinkPressEvent.kt +23 -23
- package/android/src/main/java/com/renderrichtext/events/MentionLongPressEvent.kt +25 -25
- package/android/src/main/java/com/renderrichtext/events/MentionPressEvent.kt +25 -25
- package/android/src/main/java/com/renderrichtext/events/TaskListItemPressEvent.kt +26 -26
- package/android/src/main/java/com/renderrichtext/math/LatexErrorReporter.kt +9 -9
- package/android/src/main/java/com/renderrichtext/parser/Parser.kt +59 -59
- package/android/src/main/java/com/renderrichtext/parser/TextLinkMatching.kt +35 -35
- package/android/src/main/java/com/renderrichtext/renderer/BaselineShiftRenderer.kt +45 -45
- package/android/src/main/java/com/renderrichtext/renderer/BlankLineRenderer.kt +39 -39
- package/android/src/main/java/com/renderrichtext/renderer/BlockquoteRenderer.kt +243 -243
- package/android/src/main/java/com/renderrichtext/renderer/BlockquoteTextRenderer.kt +56 -56
- package/android/src/main/java/com/renderrichtext/renderer/CodeBlockRenderer.kt +135 -135
- package/android/src/main/java/com/renderrichtext/renderer/CodeRenderer.kt +37 -37
- package/android/src/main/java/com/renderrichtext/renderer/EmphasisRenderer.kt +28 -28
- package/android/src/main/java/com/renderrichtext/renderer/HeadingRenderer.kt +81 -81
- package/android/src/main/java/com/renderrichtext/renderer/HighlightRenderer.kt +26 -26
- package/android/src/main/java/com/renderrichtext/renderer/LineBreakRenderer.kt +17 -17
- package/android/src/main/java/com/renderrichtext/renderer/LinkRenderer.kt +90 -90
- package/android/src/main/java/com/renderrichtext/renderer/ListContextManager.kt +109 -109
- package/android/src/main/java/com/renderrichtext/renderer/ListItemRenderer.kt +211 -211
- package/android/src/main/java/com/renderrichtext/renderer/ListRenderer.kt +133 -133
- package/android/src/main/java/com/renderrichtext/renderer/MentionRenderer.kt +85 -85
- package/android/src/main/java/com/renderrichtext/renderer/ParagraphRenderer.kt +91 -91
- package/android/src/main/java/com/renderrichtext/renderer/Renderer.kt +148 -148
- package/android/src/main/java/com/renderrichtext/renderer/SoftBreakRenderer.kt +17 -17
- package/android/src/main/java/com/renderrichtext/renderer/SpanStyleCache.kt +143 -143
- package/android/src/main/java/com/renderrichtext/renderer/StrikethroughRenderer.kt +28 -28
- package/android/src/main/java/com/renderrichtext/renderer/StrongRenderer.kt +28 -28
- package/android/src/main/java/com/renderrichtext/renderer/TextRenderer.kt +31 -31
- package/android/src/main/java/com/renderrichtext/renderer/ThematicBreakRenderer.kt +46 -46
- package/android/src/main/java/com/renderrichtext/renderer/UnderlineRenderer.kt +28 -28
- package/android/src/main/java/com/renderrichtext/spans/BaseListSpan.kt +164 -164
- package/android/src/main/java/com/renderrichtext/spans/BaselineShiftSpan.kt +27 -27
- package/android/src/main/java/com/renderrichtext/spans/BlockquoteSpan.kt +302 -302
- package/android/src/main/java/com/renderrichtext/spans/CodeBackgroundSpan.kt +205 -205
- package/android/src/main/java/com/renderrichtext/spans/CodeBlockSpan.kt +216 -216
- package/android/src/main/java/com/renderrichtext/spans/CodeSpan.kt +32 -32
- package/android/src/main/java/com/renderrichtext/spans/EmphasisSpan.kt +42 -42
- package/android/src/main/java/com/renderrichtext/spans/FadeInSpan.kt +29 -29
- package/android/src/main/java/com/renderrichtext/spans/HeadingSpan.kt +38 -38
- package/android/src/main/java/com/renderrichtext/spans/HighlightSpan.kt +80 -80
- package/android/src/main/java/com/renderrichtext/spans/ImageSpan.kt +481 -481
- package/android/src/main/java/com/renderrichtext/spans/InlineBackgroundGeometry.kt +42 -42
- package/android/src/main/java/com/renderrichtext/spans/LineHeightSpan.kt +39 -39
- package/android/src/main/java/com/renderrichtext/spans/LinkPillIconCache.kt +154 -154
- package/android/src/main/java/com/renderrichtext/spans/LinkPillSpan.kt +381 -381
- package/android/src/main/java/com/renderrichtext/spans/LinkSpan.kt +68 -68
- package/android/src/main/java/com/renderrichtext/spans/ListItemSpacingSpan.kt +33 -33
- package/android/src/main/java/com/renderrichtext/spans/ListMarkerAnchorSpan.kt +38 -38
- package/android/src/main/java/com/renderrichtext/spans/MarginBottomSpan.kt +76 -76
- package/android/src/main/java/com/renderrichtext/spans/MentionChipSpan.kt +132 -132
- package/android/src/main/java/com/renderrichtext/spans/MentionSpan.kt +46 -46
- package/android/src/main/java/com/renderrichtext/spans/OrderedListSpan.kt +127 -127
- package/android/src/main/java/com/renderrichtext/spans/SpoilerSpan.kt +33 -33
- package/android/src/main/java/com/renderrichtext/spans/StrikethroughSpan.kt +12 -12
- package/android/src/main/java/com/renderrichtext/spans/StrongSpan.kt +39 -39
- package/android/src/main/java/com/renderrichtext/spans/TaskListSpan.kt +143 -143
- package/android/src/main/java/com/renderrichtext/spans/TextSpan.kt +26 -26
- package/android/src/main/java/com/renderrichtext/spans/ThematicBreakSpan.kt +69 -69
- package/android/src/main/java/com/renderrichtext/spans/UnorderedListSpan.kt +96 -96
- package/android/src/main/java/com/renderrichtext/spoiler/SpoilerStubs.kt +46 -46
- package/android/src/main/java/com/renderrichtext/styles/BaseBlockStyle.kt +11 -11
- package/android/src/main/java/com/renderrichtext/styles/BlockquoteStyle.kt +83 -83
- package/android/src/main/java/com/renderrichtext/styles/CodeBlockStyle.kt +80 -80
- package/android/src/main/java/com/renderrichtext/styles/CodeStyle.kt +26 -26
- package/android/src/main/java/com/renderrichtext/styles/EmphasisStyle.kt +21 -21
- package/android/src/main/java/com/renderrichtext/styles/FactoidStyle.kt +21 -21
- package/android/src/main/java/com/renderrichtext/styles/HeadingStyle.kt +33 -33
- package/android/src/main/java/com/renderrichtext/styles/HighlightStyle.kt +19 -19
- package/android/src/main/java/com/renderrichtext/styles/ImageStyle.kt +29 -29
- package/android/src/main/java/com/renderrichtext/styles/InlineImageStyle.kt +17 -17
- package/android/src/main/java/com/renderrichtext/styles/InlineMathStyle.kt +17 -17
- package/android/src/main/java/com/renderrichtext/styles/LinkPillContent.kt +36 -36
- package/android/src/main/java/com/renderrichtext/styles/LinkPillStyle.kt +44 -44
- package/android/src/main/java/com/renderrichtext/styles/LinkStyle.kt +23 -23
- package/android/src/main/java/com/renderrichtext/styles/LinkVariantEntry.kt +34 -34
- package/android/src/main/java/com/renderrichtext/styles/ListStyle.kt +65 -65
- package/android/src/main/java/com/renderrichtext/styles/MathStyle.kt +29 -29
- package/android/src/main/java/com/renderrichtext/styles/MentionStyle.kt +19 -19
- package/android/src/main/java/com/renderrichtext/styles/ParagraphStyle.kt +33 -33
- package/android/src/main/java/com/renderrichtext/styles/SpoilerStyle.kt +27 -27
- package/android/src/main/java/com/renderrichtext/styles/StrikethroughStyle.kt +17 -17
- package/android/src/main/java/com/renderrichtext/styles/StrongStyle.kt +21 -21
- package/android/src/main/java/com/renderrichtext/styles/StyleConfig.kt +411 -411
- package/android/src/main/java/com/renderrichtext/styles/StyleParser.kt +92 -92
- package/android/src/main/java/com/renderrichtext/styles/SubscriptStyle.kt +16 -16
- package/android/src/main/java/com/renderrichtext/styles/SuperscriptStyle.kt +16 -16
- package/android/src/main/java/com/renderrichtext/styles/TableStyle.kt +75 -75
- package/android/src/main/java/com/renderrichtext/styles/TaskListStyle.kt +29 -29
- package/android/src/main/java/com/renderrichtext/styles/TextAlignment.kt +32 -32
- package/android/src/main/java/com/renderrichtext/styles/ThematicBreakStyle.kt +23 -23
- package/android/src/main/java/com/renderrichtext/styles/UnderlineStyle.kt +17 -17
- package/android/src/main/java/com/renderrichtext/styles/VideoStyle.kt +31 -31
- package/android/src/main/java/com/renderrichtext/utils/common/BorderStyleUtils.kt +86 -86
- package/android/src/main/java/com/renderrichtext/utils/common/BreakStrategyUtils.kt +32 -32
- package/android/src/main/java/com/renderrichtext/utils/common/CodeBlockHighlighter.kt +36 -36
- package/android/src/main/java/com/renderrichtext/utils/common/CodeBlockNode.kt +42 -42
- package/android/src/main/java/com/renderrichtext/utils/common/EllipsizeUtils.kt +27 -27
- package/android/src/main/java/com/renderrichtext/utils/common/EnrichedTiptapAncestorUtils.kt +10 -10
- package/android/src/main/java/com/renderrichtext/utils/common/FeatureFlags.kt +9 -9
- package/android/src/main/java/com/renderrichtext/utils/common/LinkRecognitionProps.kt +31 -31
- package/android/src/main/java/com/renderrichtext/utils/common/LinkRegexConfig.kt +56 -56
- package/android/src/main/java/com/renderrichtext/utils/common/MotionPreferences.kt +18 -18
- package/android/src/main/java/com/renderrichtext/utils/common/ReadableMapExtensions.kt +28 -28
- package/android/src/main/java/com/renderrichtext/utils/common/layout/RTLUtils.kt +6 -6
- package/android/src/main/java/com/renderrichtext/utils/common/serialization/TiptapASTSerializer.kt +368 -368
- package/android/src/main/java/com/renderrichtext/utils/text/ImageCache.kt +88 -88
- package/android/src/main/java/com/renderrichtext/utils/text/ImageDownloader.kt +203 -203
- package/android/src/main/java/com/renderrichtext/utils/text/LocalImageLoader.kt +167 -167
- package/android/src/main/java/com/renderrichtext/utils/text/TailFadeInAnimator.kt +84 -84
- package/android/src/main/java/com/renderrichtext/utils/text/conversion/HTMLGenerator.kt +1105 -1105
- package/android/src/main/java/com/renderrichtext/utils/text/conversion/TiptapExtractor.kt +423 -423
- package/android/src/main/java/com/renderrichtext/utils/text/extensions/ParagraphUtils.kt +9 -9
- package/android/src/main/java/com/renderrichtext/utils/text/extensions/SpannableExtensions.kt +9 -9
- package/android/src/main/java/com/renderrichtext/utils/text/extensions/TextPaintExtensions.kt +76 -76
- package/android/src/main/java/com/renderrichtext/utils/text/interaction/CheckboxTouchHelper.kt +61 -61
- package/android/src/main/java/com/renderrichtext/utils/text/interaction/TaskListTapUtils.kt +286 -286
- package/android/src/main/java/com/renderrichtext/utils/text/span/ApplyLineHeight.kt +39 -39
- package/android/src/main/java/com/renderrichtext/utils/text/span/BlockSpacing.kt +142 -142
- package/android/src/main/java/com/renderrichtext/utils/text/span/SpanFlags.kt +43 -43
- package/android/src/main/java/com/renderrichtext/utils/text/span/WidthAwareSpans.kt +30 -30
- package/android/src/main/java/com/renderrichtext/utils/text/view/CodeBlockPressHost.kt +15 -15
- package/android/src/main/java/com/renderrichtext/utils/text/view/ImagePressHost.kt +19 -19
- package/android/src/main/java/com/renderrichtext/utils/text/view/SelectionActionMode.kt +235 -235
- package/android/src/main/java/com/renderrichtext/utils/text/view/TextSelectionColors.kt +48 -48
- package/android/src/main/java/com/renderrichtext/utils/text/view/TextViewSetup.kt +119 -119
- package/android/src/main/java/com/renderrichtext/views/ContextMenuPopup.kt +217 -217
- package/android/src/main/java/com/renderrichtext/views/CopyGlyph.kt +101 -101
- package/android/src/main/java/com/renderrichtext/views/WrapGlyph.kt +40 -40
- package/android/src/main/jni/CMakeLists.txt +52 -52
- package/android/src/main/jni/react/renderer/components/RichTextSpec/ComponentDescriptors.h +30 -30
- package/android/src/main/jni/react/renderer/components/RichTextSpec/TiptapTextComponentDescriptor.h +29 -29
- package/android/src/main/jni/react/renderer/components/RichTextSpec/TiptapTextMeasurementManager.cpp +45 -45
- package/android/src/main/jni/react/renderer/components/RichTextSpec/TiptapTextMeasurementManager.h +21 -21
- package/android/src/main/jni/react/renderer/components/RichTextSpec/TiptapTextShadowNode.cpp +38 -38
- package/android/src/main/jni/react/renderer/components/RichTextSpec/TiptapTextShadowNode.h +53 -53
- package/android/src/main/jni/react/renderer/components/RichTextSpec/TiptapTextState.cpp +9 -9
- package/android/src/main/jni/react/renderer/components/RichTextSpec/TiptapTextState.h +24 -24
- package/android/src/main/jni/react/renderer/components/RichTextSpec/conversions.h +40 -40
- package/cpp/parser/TiptapParser.hpp +13 -13
- package/cpp/vendor/nlohmann/json.hpp +24765 -24765
- package/ios/EnrichedTiptapText.h +27 -27
- package/ios/attachments/ENRMImageAttachment.h +51 -51
- package/ios/attachments/ENRMImageAttachment.m +398 -398
- package/ios/attachments/ENRMLinkPillAttachment.h +47 -47
- package/ios/attachments/ENRMLinkPillAttachment.m +324 -324
- package/ios/attachments/ENRMLinkPillIconCache.h +28 -28
- package/ios/attachments/ENRMLinkPillIconCache.m +181 -181
- package/ios/attachments/ENRMLinkPillText.h +27 -27
- package/ios/attachments/ENRMLinkPillText.m +118 -118
- package/ios/attachments/ENRMMathInlineAttachment.h +7 -7
- package/ios/attachments/ENRMMathInlineAttachment.m +4 -4
- package/ios/attachments/ThematicBreakAttachment.h +15 -15
- package/ios/attachments/ThematicBreakAttachment.m +33 -33
- package/ios/internals/ENRMViewFreeMeasurement.h +208 -208
- package/ios/internals/EnrichedTiptapTextComponentDescriptor.h +19 -19
- package/ios/internals/EnrichedTiptapTextShadowNode.h +43 -43
- package/ios/internals/EnrichedTiptapTextShadowNode.mm +69 -69
- package/ios/internals/EnrichedTiptapTextState.h +24 -24
- package/ios/internals/MeasurementCache.h +308 -308
- package/ios/internals/ShadowMeasurementUtils.h +145 -145
- package/ios/parser/ENRMTextLinkAttributes.h +7 -7
- package/ios/parser/ENRMTiptapParser.h +33 -33
- package/ios/parser/ENRMTiptapParser.mm +73 -73
- package/ios/parser/TiptapASTNode.m +52 -52
- package/ios/renderer/AttributedRenderer.h +23 -23
- package/ios/renderer/AttributedRenderer.m +229 -229
- package/ios/renderer/BaseRenderer.h +33 -33
- package/ios/renderer/BaseRenderer.m +46 -46
- package/ios/renderer/BaselineShiftTextAttributes.h +10 -10
- package/ios/renderer/BaselineShiftTextAttributes.m +26 -26
- package/ios/renderer/BlankLineRenderer.h +4 -4
- package/ios/renderer/BlankLineRenderer.m +51 -51
- package/ios/renderer/BlockquoteRenderer.h +6 -6
- package/ios/renderer/BlockquoteRenderer.m +258 -258
- package/ios/renderer/CodeBlockRenderer.h +9 -9
- package/ios/renderer/CodeBlockRenderer.m +99 -99
- package/ios/renderer/CodeRenderer.h +9 -9
- package/ios/renderer/CodeRenderer.m +69 -69
- package/ios/renderer/ENRMBlockquoteTextRenderer.h +25 -25
- package/ios/renderer/ENRMBlockquoteTextRenderer.m +48 -48
- package/ios/renderer/EmphasisRenderer.h +5 -5
- package/ios/renderer/EmphasisRenderer.m +99 -99
- package/ios/renderer/HeadingRenderer.h +6 -6
- package/ios/renderer/HeadingRenderer.m +102 -102
- package/ios/renderer/HighlightRenderer.h +7 -7
- package/ios/renderer/HighlightRenderer.m +33 -33
- package/ios/renderer/LinkRenderer.h +6 -6
- package/ios/renderer/LinkRenderer.m +157 -157
- package/ios/renderer/ListItemRenderer.h +24 -24
- package/ios/renderer/ListItemRenderer.m +283 -283
- package/ios/renderer/ListRenderer.h +13 -13
- package/ios/renderer/ListRenderer.m +126 -126
- package/ios/renderer/MentionRenderer.h +9 -9
- package/ios/renderer/MentionRenderer.m +96 -96
- package/ios/renderer/NodeRenderer.h +8 -8
- package/ios/renderer/ParagraphRenderer.h +6 -6
- package/ios/renderer/ParagraphRenderer.m +85 -85
- package/ios/renderer/RenderContext.h +145 -145
- package/ios/renderer/RenderContext.m +402 -402
- package/ios/renderer/RendererFactory.h +12 -12
- package/ios/renderer/StrikethroughRenderer.h +5 -5
- package/ios/renderer/StrikethroughRenderer.m +30 -30
- package/ios/renderer/StrongRenderer.h +5 -5
- package/ios/renderer/StrongRenderer.m +87 -87
- package/ios/renderer/TextRenderer.h +6 -6
- package/ios/renderer/TextRenderer.m +18 -18
- package/ios/renderer/ThematicBreakRenderer.h +4 -4
- package/ios/renderer/ThematicBreakRenderer.m +41 -41
- package/ios/renderer/UnderlineRenderer.h +4 -4
- package/ios/renderer/UnderlineRenderer.m +41 -41
- package/ios/styles/ENRMFontSlot.h +12 -12
- package/ios/styles/ENRMFontSlot.m +24 -24
- package/ios/styles/StyleConfig.h +488 -488
- package/ios/styles/StyleConfig.mm +2820 -2820
- package/ios/utils/AccessibilityInfo.h +35 -35
- package/ios/utils/AccessibilityInfo.m +24 -24
- package/ios/utils/BlockquoteBorder.h +26 -26
- package/ios/utils/BlockquoteBorder.m +294 -294
- package/ios/utils/CodeBackground.h +19 -19
- package/ios/utils/CodeBackground.m +196 -196
- package/ios/utils/CodeBlockBackground.h +17 -17
- package/ios/utils/CodeBlockBackground.m +102 -102
- package/ios/utils/ContextMenuUtils.h +76 -76
- package/ios/utils/ContextMenuUtils.mm +75 -75
- package/ios/utils/ENRMAccessibilityLabels.h +40 -40
- package/ios/utils/ENRMAccessibilityLabels.m +5 -5
- package/ios/utils/ENRMAsyncRenderCoordinator.h +24 -24
- package/ios/utils/ENRMAsyncRenderCoordinator.m +37 -37
- package/ios/utils/ENRMAtomicSize.h +65 -65
- package/ios/utils/ENRMCodeBlockContent.h +37 -37
- package/ios/utils/ENRMCodeBlockContent.mm +89 -89
- package/ios/utils/ENRMFeatureFlags.h +25 -25
- package/ios/utils/ENRMImageDownloader.h +30 -30
- package/ios/utils/ENRMImageDownloader.m +168 -168
- package/ios/utils/ENRMLatexErrorCoordinator.h +27 -27
- package/ios/utils/ENRMLatexErrorCoordinator.mm +75 -75
- package/ios/utils/ENRMLatexErrorReporting.h +13 -13
- package/ios/utils/ENRMLinkContextMenus.h +93 -93
- package/ios/utils/ENRMLinkContextMenus.m +178 -178
- package/ios/utils/ENRMLinkRegexConfig.h +30 -30
- package/ios/utils/ENRMLinkRegexConfig.mm +104 -104
- package/ios/utils/ENRMLinkRegexProps.h +23 -23
- package/ios/utils/ENRMLocalImageLoader.h +35 -35
- package/ios/utils/ENRMLocalImageLoader.m +111 -111
- package/ios/utils/ENRMMenuAction.h +27 -27
- package/ios/utils/ENRMMenuAction.m +33 -33
- package/ios/utils/ENRMSpoilerOverlayManager.h +15 -15
- package/ios/utils/ENRMSpoilerOverlayManager.m +19 -19
- package/ios/utils/ENRMSpoilerTapUtils.h +6 -6
- package/ios/utils/ENRMSpoilerTapUtils.m +11 -11
- package/ios/utils/ENRMTailFadeInAnimator.h +16 -16
- package/ios/utils/ENRMTailFadeInAnimator.m +161 -161
- package/ios/utils/ENRMTextHitTest.h +23 -23
- package/ios/utils/ENRMTextHitTest.m +20 -20
- package/ios/utils/ENRMTextInteractionUtils.h +20 -20
- package/ios/utils/ENRMTextInteractionUtils.m +15 -15
- package/ios/utils/ENRMTextRenderer.h +38 -38
- package/ios/utils/ENRMTextRenderer.m +54 -54
- package/ios/utils/ENRMTextViewSetup.h +132 -132
- package/ios/utils/ENRMUIKit.h +429 -429
- package/ios/utils/EditMenuUtils.h +105 -105
- package/ios/utils/EditMenuUtils.m +143 -143
- package/ios/utils/FontScaleObserver.h +10 -10
- package/ios/utils/FontScaleObserver.m +55 -55
- package/ios/utils/FontUtils.h +31 -31
- package/ios/utils/FontUtils.m +63 -63
- package/ios/utils/HTMLGenerator.h +25 -25
- package/ios/utils/HTMLGenerator.m +1041 -1041
- package/ios/utils/HeightUpdateUtils.h +25 -25
- package/ios/utils/ImageRequestHeaderUtils.h +35 -35
- package/ios/utils/LastElementUtils.h +97 -97
- package/ios/utils/LinkContextMenuUtils.h +55 -55
- package/ios/utils/LinkPillContentUtils.h +46 -46
- package/ios/utils/ListMarkerDrawer.h +15 -15
- package/ios/utils/ListMarkerDrawer.m +239 -239
- package/ios/utils/MentionBackground.h +26 -26
- package/ios/utils/MentionBackground.m +86 -86
- package/ios/utils/ParagraphStyleUtils.h +87 -87
- package/ios/utils/ParagraphStyleUtils.m +484 -484
- package/ios/utils/PasteboardUtils.h +48 -48
- package/ios/utils/PasteboardUtils.m +166 -166
- package/ios/utils/RTFExportUtils.h +24 -24
- package/ios/utils/RTFExportUtils.m +299 -299
- package/ios/utils/SelectionColorUtils.h +14 -14
- package/ios/utils/StylePropsUtils.h +1340 -1340
- package/ios/utils/TaskListTapUtils.h +6 -6
- package/ios/utils/TaskListTapUtils.m +14 -14
- package/ios/utils/TextViewLayoutManager.h +14 -14
- package/ios/utils/TiptapAccessibilityElementBuilder.h +43 -43
- package/ios/utils/TiptapAccessibilityElementBuilder.m +432 -432
- package/ios/utils/TiptapExtractor.h +17 -17
- package/ios/utils/TiptapExtractor.m +367 -367
- package/ios/views/ENRMTiptapTextView.h +25 -25
- package/ios/views/ENRMTiptapTextView.m +247 -247
- package/package.json +65 -70
- package/react-native.config.js +10 -10
- package/src/admonitionDefaults.ts +58 -58
- package/src/darkModeTextStyle.ts +99 -99
- package/src/headingDefaults.ts +21 -21
- package/src/index.tsx +4 -4
- package/src/linkVariantUtils.ts +120 -120
- package/src/normalizeTiptapStyle.ts +397 -397
- package/src/rn-globals.d.ts +1 -1
- package/src/styleUtils.ts +107 -107
- package/src/types/TiptapStyle.ts +532 -532
- package/src/types/TiptapStyleInternal.ts +299 -299
- package/src/types/linkPill.ts +9 -9
- package/src/utils/isDev.ts +4 -4
|
@@ -1,235 +1,235 @@
|
|
|
1
|
-
package com.renderrichtext.utils.text.view
|
|
2
|
-
|
|
3
|
-
import android.content.ClipData
|
|
4
|
-
import android.content.ClipboardManager
|
|
5
|
-
import android.content.Context
|
|
6
|
-
import android.text.Spannable
|
|
7
|
-
import android.view.ActionMode
|
|
8
|
-
import android.view.Menu
|
|
9
|
-
import android.view.MenuItem
|
|
10
|
-
import android.view.ViewParent
|
|
11
|
-
import android.widget.TextView
|
|
12
|
-
import com.renderrichtext.EnrichedTiptapText
|
|
13
|
-
import com.renderrichtext.spans.ImageSpan
|
|
14
|
-
import com.renderrichtext.spans.stripFactoidPadding
|
|
15
|
-
import com.renderrichtext.styles.StyleConfig
|
|
16
|
-
import com.renderrichtext.utils.common.layout.isLayoutRTL
|
|
17
|
-
import com.renderrichtext.utils.text.conversion.HTMLGenerator
|
|
18
|
-
import com.renderrichtext.utils.text.conversion.TiptapExtractor
|
|
19
|
-
|
|
20
|
-
private const val MENU_ITEM_COPY_TIPTAP = 1000
|
|
21
|
-
private const val MENU_ITEM_COPY_IMAGE_URL = 1001
|
|
22
|
-
private const val MENU_ITEM_CUSTOM_BASE = 2000
|
|
23
|
-
private const val MENU_ITEM_CUSTOM_GROUP = 2001
|
|
24
|
-
|
|
25
|
-
data class SelectionMenuConfig(
|
|
26
|
-
val copyAsTiptap: Boolean = true,
|
|
27
|
-
val copyImageUrl: Boolean = true,
|
|
28
|
-
val copyLabel: String = "",
|
|
29
|
-
val copyAsTiptapLabel: String = "",
|
|
30
|
-
val copyImageUrlLabel: String = "",
|
|
31
|
-
val copyImageUrlsLabel: String = "",
|
|
32
|
-
// Plural templates indexed by image count (0..100). Empty when no pluralLabels
|
|
33
|
-
// are set; counts > 100 use copyImageUrlsLabel (the "other" form).
|
|
34
|
-
val copyImageUrlPluralTemplates: List<String> = emptyList(),
|
|
35
|
-
)
|
|
36
|
-
|
|
37
|
-
/**
|
|
38
|
-
* Resolves the "Copy Image URL(s)" menu title for the given image count. Uses the
|
|
39
|
-
* precomputed plural templates when present (counts > 100 use the "other" form),
|
|
40
|
-
* otherwise the singular/`{count}` templates. All labels are resolved JS-side.
|
|
41
|
-
*/
|
|
42
|
-
private fun SelectionMenuConfig.imageUrlsTitle(count: Int): String {
|
|
43
|
-
val template =
|
|
44
|
-
when {
|
|
45
|
-
copyImageUrlPluralTemplates.isNotEmpty() && count in 0..100 -> copyImageUrlPluralTemplates[count]
|
|
46
|
-
count == 1 -> copyImageUrlLabel
|
|
47
|
-
else -> copyImageUrlsLabel
|
|
48
|
-
}
|
|
49
|
-
return template.replace("{count}", count.toString())
|
|
50
|
-
}
|
|
51
|
-
|
|
52
|
-
/**
|
|
53
|
-
* Creates an ActionMode.Callback that adds custom copy options and
|
|
54
|
-
* overrides the default "Copy" action to include HTML for rich text support.
|
|
55
|
-
*/
|
|
56
|
-
fun createSelectionActionModeCallback(
|
|
57
|
-
textView: TextView,
|
|
58
|
-
getCustomItemTexts: () -> List<String> = { emptyList() },
|
|
59
|
-
getSelectionMenuConfig: () -> SelectionMenuConfig = { SelectionMenuConfig() },
|
|
60
|
-
onCustomItemPress: (itemText: String, selectedText: String, selectionStart: Int, selectionEnd: Int) -> Unit =
|
|
61
|
-
{ _, _, _, _ -> },
|
|
62
|
-
): ActionMode.Callback =
|
|
63
|
-
object : ActionMode.Callback {
|
|
64
|
-
override fun onCreateActionMode(
|
|
65
|
-
mode: ActionMode?,
|
|
66
|
-
menu: Menu?,
|
|
67
|
-
): Boolean = true
|
|
68
|
-
|
|
69
|
-
override fun onPrepareActionMode(
|
|
70
|
-
mode: ActionMode?,
|
|
71
|
-
menu: Menu?,
|
|
72
|
-
): Boolean {
|
|
73
|
-
if (menu == null) return false
|
|
74
|
-
|
|
75
|
-
menu.removeItem(MENU_ITEM_COPY_TIPTAP)
|
|
76
|
-
menu.removeItem(MENU_ITEM_COPY_IMAGE_URL)
|
|
77
|
-
menu.removeGroup(MENU_ITEM_CUSTOM_GROUP)
|
|
78
|
-
|
|
79
|
-
val selectionMenuConfig = getSelectionMenuConfig()
|
|
80
|
-
|
|
81
|
-
// The system Copy item is added by the platform; relabel it so it
|
|
82
|
-
// matches the rest of the localized menu (iOS rebuilds the menu so
|
|
83
|
-
// gets this for free; Android only intercepts the click).
|
|
84
|
-
if (selectionMenuConfig.copyLabel.isNotEmpty()) {
|
|
85
|
-
menu.findItem(android.R.id.copy)?.title = selectionMenuConfig.copyLabel
|
|
86
|
-
}
|
|
87
|
-
|
|
88
|
-
if (
|
|
89
|
-
selectionMenuConfig.copyAsTiptap &&
|
|
90
|
-
textView.selectionStart >= 0 &&
|
|
91
|
-
textView.selectionEnd > textView.selectionStart
|
|
92
|
-
) {
|
|
93
|
-
menu.add(
|
|
94
|
-
Menu.NONE,
|
|
95
|
-
MENU_ITEM_COPY_TIPTAP,
|
|
96
|
-
Menu.NONE,
|
|
97
|
-
selectionMenuConfig.copyAsTiptapLabel,
|
|
98
|
-
)
|
|
99
|
-
}
|
|
100
|
-
|
|
101
|
-
if (textView.selectionStart >= 0 && textView.selectionEnd > textView.selectionStart) {
|
|
102
|
-
val customItems = getCustomItemTexts()
|
|
103
|
-
customItems.forEachIndexed { index, text ->
|
|
104
|
-
menu
|
|
105
|
-
.add(MENU_ITEM_CUSTOM_GROUP, MENU_ITEM_CUSTOM_BASE + index, index, text)
|
|
106
|
-
.setShowAsAction(MenuItem.SHOW_AS_ACTION_ALWAYS)
|
|
107
|
-
}
|
|
108
|
-
}
|
|
109
|
-
|
|
110
|
-
val imageUrls =
|
|
111
|
-
if (selectionMenuConfig.copyImageUrl) {
|
|
112
|
-
textView.getImageUrlsInSelection()
|
|
113
|
-
} else {
|
|
114
|
-
emptyList()
|
|
115
|
-
}
|
|
116
|
-
if (imageUrls.isNotEmpty()) {
|
|
117
|
-
val title = selectionMenuConfig.imageUrlsTitle(imageUrls.size)
|
|
118
|
-
menu.add(Menu.NONE, MENU_ITEM_COPY_IMAGE_URL, Menu.NONE, title)
|
|
119
|
-
}
|
|
120
|
-
|
|
121
|
-
return true
|
|
122
|
-
}
|
|
123
|
-
|
|
124
|
-
override fun onActionItemClicked(
|
|
125
|
-
mode: ActionMode?,
|
|
126
|
-
item: MenuItem?,
|
|
127
|
-
): Boolean {
|
|
128
|
-
val itemId = item?.itemId ?: return false
|
|
129
|
-
|
|
130
|
-
when (itemId) {
|
|
131
|
-
android.R.id.copy -> {
|
|
132
|
-
textView.copyWithHTML()
|
|
133
|
-
mode?.finish()
|
|
134
|
-
return true
|
|
135
|
-
}
|
|
136
|
-
|
|
137
|
-
MENU_ITEM_COPY_TIPTAP -> {
|
|
138
|
-
textView.copyTiptapToClipboard()
|
|
139
|
-
mode?.finish()
|
|
140
|
-
return true
|
|
141
|
-
}
|
|
142
|
-
|
|
143
|
-
MENU_ITEM_COPY_IMAGE_URL -> {
|
|
144
|
-
textView.copyImageUrlsToClipboard()
|
|
145
|
-
mode?.finish()
|
|
146
|
-
return true
|
|
147
|
-
}
|
|
148
|
-
}
|
|
149
|
-
|
|
150
|
-
val customItems = getCustomItemTexts()
|
|
151
|
-
val customIndex = itemId - MENU_ITEM_CUSTOM_BASE
|
|
152
|
-
if (customIndex in customItems.indices) {
|
|
153
|
-
val start = textView.selectionStart
|
|
154
|
-
val end = textView.selectionEnd
|
|
155
|
-
val selectedText =
|
|
156
|
-
if (start >= 0 && end > start) textView.text.subSequence(start, end).stripFactoidPadding() else ""
|
|
157
|
-
onCustomItemPress(customItems[customIndex], selectedText, start, end)
|
|
158
|
-
mode?.finish()
|
|
159
|
-
return true
|
|
160
|
-
}
|
|
161
|
-
|
|
162
|
-
return false
|
|
163
|
-
}
|
|
164
|
-
|
|
165
|
-
override fun onDestroyActionMode(mode: ActionMode?) {}
|
|
166
|
-
}
|
|
167
|
-
|
|
168
|
-
/** Copies selection as both plain text and HTML with inline styles. */
|
|
169
|
-
private fun TextView.copyWithHTML() {
|
|
170
|
-
val start = selectionStart
|
|
171
|
-
val end = selectionEnd
|
|
172
|
-
if (start < 0 || end < 0 || start >= end) return
|
|
173
|
-
|
|
174
|
-
val spannable = text as? Spannable ?: return
|
|
175
|
-
val selectedText = spannable.subSequence(start, end)
|
|
176
|
-
val plainText = selectedText.stripFactoidPadding()
|
|
177
|
-
|
|
178
|
-
val styleConfig =
|
|
179
|
-
(this as? EnrichedTiptapText)?.tiptapStyle
|
|
180
|
-
?: findParentTiptapStyle()
|
|
181
|
-
val clipboard = context.getSystemService(Context.CLIPBOARD_SERVICE) as ClipboardManager
|
|
182
|
-
|
|
183
|
-
if (styleConfig != null && selectedText is Spannable) {
|
|
184
|
-
// Density values convert device pixels back to CSS pixels
|
|
185
|
-
val displayMetrics = context.resources.displayMetrics
|
|
186
|
-
val isRTL = context.resources.isLayoutRTL()
|
|
187
|
-
val html =
|
|
188
|
-
HTMLGenerator.generateHTML(
|
|
189
|
-
selectedText,
|
|
190
|
-
styleConfig,
|
|
191
|
-
displayMetrics.scaledDensity,
|
|
192
|
-
displayMetrics.density,
|
|
193
|
-
isRTL,
|
|
194
|
-
)
|
|
195
|
-
clipboard.setPrimaryClip(ClipData.newHtmlText("EnrichedTiptap", plainText, html))
|
|
196
|
-
} else {
|
|
197
|
-
clipboard.setPrimaryClip(ClipData.newPlainText("Text", plainText))
|
|
198
|
-
}
|
|
199
|
-
}
|
|
200
|
-
|
|
201
|
-
private fun TextView.copyTiptapToClipboard() {
|
|
202
|
-
val tiptap = TiptapExtractor.getTiptapForSelection(this) ?: return
|
|
203
|
-
val clipboard = context.getSystemService(Context.CLIPBOARD_SERVICE) as ClipboardManager
|
|
204
|
-
clipboard.setPrimaryClip(ClipData.newPlainText("Tiptap", tiptap))
|
|
205
|
-
}
|
|
206
|
-
|
|
207
|
-
/** Returns remote image URLs (http/https only) from the current selection. */
|
|
208
|
-
private fun TextView.getImageUrlsInSelection(): List<String> {
|
|
209
|
-
val start = selectionStart
|
|
210
|
-
val end = selectionEnd
|
|
211
|
-
if (start < 0 || end < 0 || start >= end) return emptyList()
|
|
212
|
-
|
|
213
|
-
val spannable = text as? Spannable ?: return emptyList()
|
|
214
|
-
return spannable
|
|
215
|
-
.getSpans(start, end, ImageSpan::class.java)
|
|
216
|
-
.mapNotNull { it.imageUrl }
|
|
217
|
-
.filter { it.startsWith("http://") || it.startsWith("https://") }
|
|
218
|
-
}
|
|
219
|
-
|
|
220
|
-
private fun TextView.copyImageUrlsToClipboard() {
|
|
221
|
-
val urls = getImageUrlsInSelection()
|
|
222
|
-
if (urls.isEmpty()) return
|
|
223
|
-
|
|
224
|
-
val clipboard = context.getSystemService(Context.CLIPBOARD_SERVICE) as ClipboardManager
|
|
225
|
-
clipboard.setPrimaryClip(ClipData.newPlainText("Image URLs", urls.joinToString("\n")))
|
|
226
|
-
}
|
|
227
|
-
|
|
228
|
-
private fun TextView.findParentTiptapStyle(): StyleConfig? {
|
|
229
|
-
var current: ViewParent? = parent
|
|
230
|
-
while (current != null) {
|
|
231
|
-
if (current is EnrichedTiptapText) return current.tiptapStyle
|
|
232
|
-
current = current.parent
|
|
233
|
-
}
|
|
234
|
-
return null
|
|
235
|
-
}
|
|
1
|
+
package com.renderrichtext.utils.text.view
|
|
2
|
+
|
|
3
|
+
import android.content.ClipData
|
|
4
|
+
import android.content.ClipboardManager
|
|
5
|
+
import android.content.Context
|
|
6
|
+
import android.text.Spannable
|
|
7
|
+
import android.view.ActionMode
|
|
8
|
+
import android.view.Menu
|
|
9
|
+
import android.view.MenuItem
|
|
10
|
+
import android.view.ViewParent
|
|
11
|
+
import android.widget.TextView
|
|
12
|
+
import com.renderrichtext.EnrichedTiptapText
|
|
13
|
+
import com.renderrichtext.spans.ImageSpan
|
|
14
|
+
import com.renderrichtext.spans.stripFactoidPadding
|
|
15
|
+
import com.renderrichtext.styles.StyleConfig
|
|
16
|
+
import com.renderrichtext.utils.common.layout.isLayoutRTL
|
|
17
|
+
import com.renderrichtext.utils.text.conversion.HTMLGenerator
|
|
18
|
+
import com.renderrichtext.utils.text.conversion.TiptapExtractor
|
|
19
|
+
|
|
20
|
+
private const val MENU_ITEM_COPY_TIPTAP = 1000
|
|
21
|
+
private const val MENU_ITEM_COPY_IMAGE_URL = 1001
|
|
22
|
+
private const val MENU_ITEM_CUSTOM_BASE = 2000
|
|
23
|
+
private const val MENU_ITEM_CUSTOM_GROUP = 2001
|
|
24
|
+
|
|
25
|
+
data class SelectionMenuConfig(
|
|
26
|
+
val copyAsTiptap: Boolean = true,
|
|
27
|
+
val copyImageUrl: Boolean = true,
|
|
28
|
+
val copyLabel: String = "",
|
|
29
|
+
val copyAsTiptapLabel: String = "",
|
|
30
|
+
val copyImageUrlLabel: String = "",
|
|
31
|
+
val copyImageUrlsLabel: String = "",
|
|
32
|
+
// Plural templates indexed by image count (0..100). Empty when no pluralLabels
|
|
33
|
+
// are set; counts > 100 use copyImageUrlsLabel (the "other" form).
|
|
34
|
+
val copyImageUrlPluralTemplates: List<String> = emptyList(),
|
|
35
|
+
)
|
|
36
|
+
|
|
37
|
+
/**
|
|
38
|
+
* Resolves the "Copy Image URL(s)" menu title for the given image count. Uses the
|
|
39
|
+
* precomputed plural templates when present (counts > 100 use the "other" form),
|
|
40
|
+
* otherwise the singular/`{count}` templates. All labels are resolved JS-side.
|
|
41
|
+
*/
|
|
42
|
+
private fun SelectionMenuConfig.imageUrlsTitle(count: Int): String {
|
|
43
|
+
val template =
|
|
44
|
+
when {
|
|
45
|
+
copyImageUrlPluralTemplates.isNotEmpty() && count in 0..100 -> copyImageUrlPluralTemplates[count]
|
|
46
|
+
count == 1 -> copyImageUrlLabel
|
|
47
|
+
else -> copyImageUrlsLabel
|
|
48
|
+
}
|
|
49
|
+
return template.replace("{count}", count.toString())
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
/**
|
|
53
|
+
* Creates an ActionMode.Callback that adds custom copy options and
|
|
54
|
+
* overrides the default "Copy" action to include HTML for rich text support.
|
|
55
|
+
*/
|
|
56
|
+
fun createSelectionActionModeCallback(
|
|
57
|
+
textView: TextView,
|
|
58
|
+
getCustomItemTexts: () -> List<String> = { emptyList() },
|
|
59
|
+
getSelectionMenuConfig: () -> SelectionMenuConfig = { SelectionMenuConfig() },
|
|
60
|
+
onCustomItemPress: (itemText: String, selectedText: String, selectionStart: Int, selectionEnd: Int) -> Unit =
|
|
61
|
+
{ _, _, _, _ -> },
|
|
62
|
+
): ActionMode.Callback =
|
|
63
|
+
object : ActionMode.Callback {
|
|
64
|
+
override fun onCreateActionMode(
|
|
65
|
+
mode: ActionMode?,
|
|
66
|
+
menu: Menu?,
|
|
67
|
+
): Boolean = true
|
|
68
|
+
|
|
69
|
+
override fun onPrepareActionMode(
|
|
70
|
+
mode: ActionMode?,
|
|
71
|
+
menu: Menu?,
|
|
72
|
+
): Boolean {
|
|
73
|
+
if (menu == null) return false
|
|
74
|
+
|
|
75
|
+
menu.removeItem(MENU_ITEM_COPY_TIPTAP)
|
|
76
|
+
menu.removeItem(MENU_ITEM_COPY_IMAGE_URL)
|
|
77
|
+
menu.removeGroup(MENU_ITEM_CUSTOM_GROUP)
|
|
78
|
+
|
|
79
|
+
val selectionMenuConfig = getSelectionMenuConfig()
|
|
80
|
+
|
|
81
|
+
// The system Copy item is added by the platform; relabel it so it
|
|
82
|
+
// matches the rest of the localized menu (iOS rebuilds the menu so
|
|
83
|
+
// gets this for free; Android only intercepts the click).
|
|
84
|
+
if (selectionMenuConfig.copyLabel.isNotEmpty()) {
|
|
85
|
+
menu.findItem(android.R.id.copy)?.title = selectionMenuConfig.copyLabel
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
if (
|
|
89
|
+
selectionMenuConfig.copyAsTiptap &&
|
|
90
|
+
textView.selectionStart >= 0 &&
|
|
91
|
+
textView.selectionEnd > textView.selectionStart
|
|
92
|
+
) {
|
|
93
|
+
menu.add(
|
|
94
|
+
Menu.NONE,
|
|
95
|
+
MENU_ITEM_COPY_TIPTAP,
|
|
96
|
+
Menu.NONE,
|
|
97
|
+
selectionMenuConfig.copyAsTiptapLabel,
|
|
98
|
+
)
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
if (textView.selectionStart >= 0 && textView.selectionEnd > textView.selectionStart) {
|
|
102
|
+
val customItems = getCustomItemTexts()
|
|
103
|
+
customItems.forEachIndexed { index, text ->
|
|
104
|
+
menu
|
|
105
|
+
.add(MENU_ITEM_CUSTOM_GROUP, MENU_ITEM_CUSTOM_BASE + index, index, text)
|
|
106
|
+
.setShowAsAction(MenuItem.SHOW_AS_ACTION_ALWAYS)
|
|
107
|
+
}
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
val imageUrls =
|
|
111
|
+
if (selectionMenuConfig.copyImageUrl) {
|
|
112
|
+
textView.getImageUrlsInSelection()
|
|
113
|
+
} else {
|
|
114
|
+
emptyList()
|
|
115
|
+
}
|
|
116
|
+
if (imageUrls.isNotEmpty()) {
|
|
117
|
+
val title = selectionMenuConfig.imageUrlsTitle(imageUrls.size)
|
|
118
|
+
menu.add(Menu.NONE, MENU_ITEM_COPY_IMAGE_URL, Menu.NONE, title)
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
return true
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
override fun onActionItemClicked(
|
|
125
|
+
mode: ActionMode?,
|
|
126
|
+
item: MenuItem?,
|
|
127
|
+
): Boolean {
|
|
128
|
+
val itemId = item?.itemId ?: return false
|
|
129
|
+
|
|
130
|
+
when (itemId) {
|
|
131
|
+
android.R.id.copy -> {
|
|
132
|
+
textView.copyWithHTML()
|
|
133
|
+
mode?.finish()
|
|
134
|
+
return true
|
|
135
|
+
}
|
|
136
|
+
|
|
137
|
+
MENU_ITEM_COPY_TIPTAP -> {
|
|
138
|
+
textView.copyTiptapToClipboard()
|
|
139
|
+
mode?.finish()
|
|
140
|
+
return true
|
|
141
|
+
}
|
|
142
|
+
|
|
143
|
+
MENU_ITEM_COPY_IMAGE_URL -> {
|
|
144
|
+
textView.copyImageUrlsToClipboard()
|
|
145
|
+
mode?.finish()
|
|
146
|
+
return true
|
|
147
|
+
}
|
|
148
|
+
}
|
|
149
|
+
|
|
150
|
+
val customItems = getCustomItemTexts()
|
|
151
|
+
val customIndex = itemId - MENU_ITEM_CUSTOM_BASE
|
|
152
|
+
if (customIndex in customItems.indices) {
|
|
153
|
+
val start = textView.selectionStart
|
|
154
|
+
val end = textView.selectionEnd
|
|
155
|
+
val selectedText =
|
|
156
|
+
if (start >= 0 && end > start) textView.text.subSequence(start, end).stripFactoidPadding() else ""
|
|
157
|
+
onCustomItemPress(customItems[customIndex], selectedText, start, end)
|
|
158
|
+
mode?.finish()
|
|
159
|
+
return true
|
|
160
|
+
}
|
|
161
|
+
|
|
162
|
+
return false
|
|
163
|
+
}
|
|
164
|
+
|
|
165
|
+
override fun onDestroyActionMode(mode: ActionMode?) {}
|
|
166
|
+
}
|
|
167
|
+
|
|
168
|
+
/** Copies selection as both plain text and HTML with inline styles. */
|
|
169
|
+
private fun TextView.copyWithHTML() {
|
|
170
|
+
val start = selectionStart
|
|
171
|
+
val end = selectionEnd
|
|
172
|
+
if (start < 0 || end < 0 || start >= end) return
|
|
173
|
+
|
|
174
|
+
val spannable = text as? Spannable ?: return
|
|
175
|
+
val selectedText = spannable.subSequence(start, end)
|
|
176
|
+
val plainText = selectedText.stripFactoidPadding()
|
|
177
|
+
|
|
178
|
+
val styleConfig =
|
|
179
|
+
(this as? EnrichedTiptapText)?.tiptapStyle
|
|
180
|
+
?: findParentTiptapStyle()
|
|
181
|
+
val clipboard = context.getSystemService(Context.CLIPBOARD_SERVICE) as ClipboardManager
|
|
182
|
+
|
|
183
|
+
if (styleConfig != null && selectedText is Spannable) {
|
|
184
|
+
// Density values convert device pixels back to CSS pixels
|
|
185
|
+
val displayMetrics = context.resources.displayMetrics
|
|
186
|
+
val isRTL = context.resources.isLayoutRTL()
|
|
187
|
+
val html =
|
|
188
|
+
HTMLGenerator.generateHTML(
|
|
189
|
+
selectedText,
|
|
190
|
+
styleConfig,
|
|
191
|
+
displayMetrics.scaledDensity,
|
|
192
|
+
displayMetrics.density,
|
|
193
|
+
isRTL,
|
|
194
|
+
)
|
|
195
|
+
clipboard.setPrimaryClip(ClipData.newHtmlText("EnrichedTiptap", plainText, html))
|
|
196
|
+
} else {
|
|
197
|
+
clipboard.setPrimaryClip(ClipData.newPlainText("Text", plainText))
|
|
198
|
+
}
|
|
199
|
+
}
|
|
200
|
+
|
|
201
|
+
private fun TextView.copyTiptapToClipboard() {
|
|
202
|
+
val tiptap = TiptapExtractor.getTiptapForSelection(this) ?: return
|
|
203
|
+
val clipboard = context.getSystemService(Context.CLIPBOARD_SERVICE) as ClipboardManager
|
|
204
|
+
clipboard.setPrimaryClip(ClipData.newPlainText("Tiptap", tiptap))
|
|
205
|
+
}
|
|
206
|
+
|
|
207
|
+
/** Returns remote image URLs (http/https only) from the current selection. */
|
|
208
|
+
private fun TextView.getImageUrlsInSelection(): List<String> {
|
|
209
|
+
val start = selectionStart
|
|
210
|
+
val end = selectionEnd
|
|
211
|
+
if (start < 0 || end < 0 || start >= end) return emptyList()
|
|
212
|
+
|
|
213
|
+
val spannable = text as? Spannable ?: return emptyList()
|
|
214
|
+
return spannable
|
|
215
|
+
.getSpans(start, end, ImageSpan::class.java)
|
|
216
|
+
.mapNotNull { it.imageUrl }
|
|
217
|
+
.filter { it.startsWith("http://") || it.startsWith("https://") }
|
|
218
|
+
}
|
|
219
|
+
|
|
220
|
+
private fun TextView.copyImageUrlsToClipboard() {
|
|
221
|
+
val urls = getImageUrlsInSelection()
|
|
222
|
+
if (urls.isEmpty()) return
|
|
223
|
+
|
|
224
|
+
val clipboard = context.getSystemService(Context.CLIPBOARD_SERVICE) as ClipboardManager
|
|
225
|
+
clipboard.setPrimaryClip(ClipData.newPlainText("Image URLs", urls.joinToString("\n")))
|
|
226
|
+
}
|
|
227
|
+
|
|
228
|
+
private fun TextView.findParentTiptapStyle(): StyleConfig? {
|
|
229
|
+
var current: ViewParent? = parent
|
|
230
|
+
while (current != null) {
|
|
231
|
+
if (current is EnrichedTiptapText) return current.tiptapStyle
|
|
232
|
+
current = current.parent
|
|
233
|
+
}
|
|
234
|
+
return null
|
|
235
|
+
}
|
|
@@ -1,48 +1,48 @@
|
|
|
1
|
-
package com.renderrichtext.utils.text.view
|
|
2
|
-
|
|
3
|
-
import android.graphics.drawable.Drawable
|
|
4
|
-
import android.os.Build
|
|
5
|
-
import android.util.Log
|
|
6
|
-
import android.widget.TextView
|
|
7
|
-
import androidx.annotation.ColorInt
|
|
8
|
-
import androidx.core.graphics.drawable.DrawableCompat
|
|
9
|
-
|
|
10
|
-
private const val TAG = "TextSelectionColors"
|
|
11
|
-
|
|
12
|
-
private typealias HandleGetter = (TextView) -> Drawable?
|
|
13
|
-
private typealias HandleSetter = (TextView, Drawable) -> Unit
|
|
14
|
-
|
|
15
|
-
/**
|
|
16
|
-
* Applies selection highlight and (where supported) handle tinting to a [TextView].
|
|
17
|
-
*
|
|
18
|
-
* Handle drawables are only tinted on API 29+ where the framework exposes getters;
|
|
19
|
-
* on older versions the handle theme defaults remain unchanged.
|
|
20
|
-
*/
|
|
21
|
-
fun TextView.applySelectionColors(
|
|
22
|
-
selectionColor: Int?,
|
|
23
|
-
selectionHandleColor: Int?,
|
|
24
|
-
) {
|
|
25
|
-
selectionColor?.let { highlightColor = it }
|
|
26
|
-
selectionHandleColor?.let { applySelectionHandleTint(it) }
|
|
27
|
-
}
|
|
28
|
-
|
|
29
|
-
private fun TextView.applySelectionHandleTint(
|
|
30
|
-
@ColorInt color: Int,
|
|
31
|
-
) {
|
|
32
|
-
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.Q) return
|
|
33
|
-
|
|
34
|
-
val handles: List<Pair<HandleGetter, HandleSetter>> =
|
|
35
|
-
listOf(
|
|
36
|
-
TextView::getTextSelectHandleLeft to { tv, d -> tv.setTextSelectHandleLeft(d) },
|
|
37
|
-
TextView::getTextSelectHandle to { tv, d -> tv.setTextSelectHandle(d) },
|
|
38
|
-
TextView::getTextSelectHandleRight to { tv, d -> tv.setTextSelectHandleRight(d) },
|
|
39
|
-
)
|
|
40
|
-
|
|
41
|
-
handles.forEach { (getter, setter) ->
|
|
42
|
-
try {
|
|
43
|
-
getter(this)?.mutate()?.also { DrawableCompat.setTint(it, color) }?.let { setter(this, it) }
|
|
44
|
-
} catch (e: LinkageError) {
|
|
45
|
-
Log.w(TAG, "Selection handle tint skipped: ${e.message}")
|
|
46
|
-
}
|
|
47
|
-
}
|
|
48
|
-
}
|
|
1
|
+
package com.renderrichtext.utils.text.view
|
|
2
|
+
|
|
3
|
+
import android.graphics.drawable.Drawable
|
|
4
|
+
import android.os.Build
|
|
5
|
+
import android.util.Log
|
|
6
|
+
import android.widget.TextView
|
|
7
|
+
import androidx.annotation.ColorInt
|
|
8
|
+
import androidx.core.graphics.drawable.DrawableCompat
|
|
9
|
+
|
|
10
|
+
private const val TAG = "TextSelectionColors"
|
|
11
|
+
|
|
12
|
+
private typealias HandleGetter = (TextView) -> Drawable?
|
|
13
|
+
private typealias HandleSetter = (TextView, Drawable) -> Unit
|
|
14
|
+
|
|
15
|
+
/**
|
|
16
|
+
* Applies selection highlight and (where supported) handle tinting to a [TextView].
|
|
17
|
+
*
|
|
18
|
+
* Handle drawables are only tinted on API 29+ where the framework exposes getters;
|
|
19
|
+
* on older versions the handle theme defaults remain unchanged.
|
|
20
|
+
*/
|
|
21
|
+
fun TextView.applySelectionColors(
|
|
22
|
+
selectionColor: Int?,
|
|
23
|
+
selectionHandleColor: Int?,
|
|
24
|
+
) {
|
|
25
|
+
selectionColor?.let { highlightColor = it }
|
|
26
|
+
selectionHandleColor?.let { applySelectionHandleTint(it) }
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
private fun TextView.applySelectionHandleTint(
|
|
30
|
+
@ColorInt color: Int,
|
|
31
|
+
) {
|
|
32
|
+
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.Q) return
|
|
33
|
+
|
|
34
|
+
val handles: List<Pair<HandleGetter, HandleSetter>> =
|
|
35
|
+
listOf(
|
|
36
|
+
TextView::getTextSelectHandleLeft to { tv, d -> tv.setTextSelectHandleLeft(d) },
|
|
37
|
+
TextView::getTextSelectHandle to { tv, d -> tv.setTextSelectHandle(d) },
|
|
38
|
+
TextView::getTextSelectHandleRight to { tv, d -> tv.setTextSelectHandleRight(d) },
|
|
39
|
+
)
|
|
40
|
+
|
|
41
|
+
handles.forEach { (getter, setter) ->
|
|
42
|
+
try {
|
|
43
|
+
getter(this)?.mutate()?.also { DrawableCompat.setTint(it, color) }?.let { setter(this, it) }
|
|
44
|
+
} catch (e: LinkageError) {
|
|
45
|
+
Log.w(TAG, "Selection handle tint skipped: ${e.message}")
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
}
|