@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,27 +1,27 @@
|
|
|
1
|
-
package com.renderrichtext.spans
|
|
2
|
-
|
|
3
|
-
import android.text.TextPaint
|
|
4
|
-
import android.text.style.MetricAffectingSpan
|
|
5
|
-
import kotlin.math.roundToInt
|
|
6
|
-
|
|
7
|
-
class BaselineShiftSpan(
|
|
8
|
-
private val fontScale: Float,
|
|
9
|
-
private val baselineOffsetScale: Float,
|
|
10
|
-
val spanType: SpanType,
|
|
11
|
-
) : MetricAffectingSpan() {
|
|
12
|
-
enum class SpanType { SUPERSCRIPT, SUBSCRIPT }
|
|
13
|
-
|
|
14
|
-
override fun updateDrawState(tp: TextPaint) {
|
|
15
|
-
applyShift(tp)
|
|
16
|
-
}
|
|
17
|
-
|
|
18
|
-
override fun updateMeasureState(tp: TextPaint) {
|
|
19
|
-
applyShift(tp)
|
|
20
|
-
}
|
|
21
|
-
|
|
22
|
-
private fun applyShift(tp: TextPaint) {
|
|
23
|
-
val originalTextSize = tp.textSize
|
|
24
|
-
tp.textSize = originalTextSize * fontScale
|
|
25
|
-
tp.baselineShift -= (originalTextSize * baselineOffsetScale).roundToInt()
|
|
26
|
-
}
|
|
27
|
-
}
|
|
1
|
+
package com.renderrichtext.spans
|
|
2
|
+
|
|
3
|
+
import android.text.TextPaint
|
|
4
|
+
import android.text.style.MetricAffectingSpan
|
|
5
|
+
import kotlin.math.roundToInt
|
|
6
|
+
|
|
7
|
+
class BaselineShiftSpan(
|
|
8
|
+
private val fontScale: Float,
|
|
9
|
+
private val baselineOffsetScale: Float,
|
|
10
|
+
val spanType: SpanType,
|
|
11
|
+
) : MetricAffectingSpan() {
|
|
12
|
+
enum class SpanType { SUPERSCRIPT, SUBSCRIPT }
|
|
13
|
+
|
|
14
|
+
override fun updateDrawState(tp: TextPaint) {
|
|
15
|
+
applyShift(tp)
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
override fun updateMeasureState(tp: TextPaint) {
|
|
19
|
+
applyShift(tp)
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
private fun applyShift(tp: TextPaint) {
|
|
23
|
+
val originalTextSize = tp.textSize
|
|
24
|
+
tp.textSize = originalTextSize * fontScale
|
|
25
|
+
tp.baselineShift -= (originalTextSize * baselineOffsetScale).roundToInt()
|
|
26
|
+
}
|
|
27
|
+
}
|
|
@@ -1,302 +1,302 @@
|
|
|
1
|
-
package com.renderrichtext.spans
|
|
2
|
-
|
|
3
|
-
import android.annotation.SuppressLint
|
|
4
|
-
import android.content.Context
|
|
5
|
-
import android.graphics.Canvas
|
|
6
|
-
import android.graphics.Color
|
|
7
|
-
import android.graphics.Paint
|
|
8
|
-
import android.graphics.Path
|
|
9
|
-
import android.graphics.RectF
|
|
10
|
-
import android.graphics.Typeface
|
|
11
|
-
import android.text.Layout
|
|
12
|
-
import android.text.Spanned
|
|
13
|
-
import android.text.TextPaint
|
|
14
|
-
import android.text.style.LeadingMarginSpan
|
|
15
|
-
import android.text.style.LineBackgroundSpan
|
|
16
|
-
import android.text.style.MetricAffectingSpan
|
|
17
|
-
import androidx.core.graphics.withSave
|
|
18
|
-
import com.renderrichtext.renderer.BlockStyle
|
|
19
|
-
import com.renderrichtext.renderer.SpanStyleCache
|
|
20
|
-
import com.renderrichtext.styles.BlockquoteStyle
|
|
21
|
-
import com.renderrichtext.utils.text.extensions.applyBlockStyleFont
|
|
22
|
-
import com.renderrichtext.utils.text.extensions.applyColorPreserving
|
|
23
|
-
|
|
24
|
-
class BlockquoteSpan(
|
|
25
|
-
private val blockquoteStyle: BlockquoteStyle,
|
|
26
|
-
val depth: Int,
|
|
27
|
-
private val context: Context,
|
|
28
|
-
private val styleCache: SpanStyleCache,
|
|
29
|
-
) : MetricAffectingSpan(),
|
|
30
|
-
LeadingMarginSpan,
|
|
31
|
-
LineBackgroundSpan {
|
|
32
|
-
private val levelSpacing: Float = blockquoteStyle.borderWidth + blockquoteStyle.gapWidth
|
|
33
|
-
private val blockStyle =
|
|
34
|
-
BlockStyle(
|
|
35
|
-
fontSize = blockquoteStyle.fontSize,
|
|
36
|
-
fontFamily = blockquoteStyle.fontFamily,
|
|
37
|
-
fontWeight = blockquoteStyle.fontWeight,
|
|
38
|
-
color = blockquoteStyle.color,
|
|
39
|
-
)
|
|
40
|
-
|
|
41
|
-
// Cache for shouldSkipDrawing to avoid repeated getSpans() calls during draw passes
|
|
42
|
-
private var cachedText: CharSequence? = null
|
|
43
|
-
private var cachedSpansByPosition = mutableMapOf<Int, Array<BlockquoteSpan>>()
|
|
44
|
-
private var boxLeft = 0f
|
|
45
|
-
private var boxRight = 0f
|
|
46
|
-
|
|
47
|
-
private val path = Path()
|
|
48
|
-
private val rect = RectF()
|
|
49
|
-
private val radiiArray = FloatArray(8)
|
|
50
|
-
|
|
51
|
-
override fun updateMeasureState(tp: TextPaint) = applyTextStyle(tp)
|
|
52
|
-
|
|
53
|
-
override fun updateDrawState(tp: TextPaint) = applyTextStyle(tp)
|
|
54
|
-
|
|
55
|
-
override fun getLeadingMargin(first: Boolean): Int = levelSpacing.toInt()
|
|
56
|
-
|
|
57
|
-
override fun drawLeadingMargin(
|
|
58
|
-
c: Canvas,
|
|
59
|
-
p: Paint,
|
|
60
|
-
x: Int,
|
|
61
|
-
dir: Int,
|
|
62
|
-
top: Int,
|
|
63
|
-
baseline: Int,
|
|
64
|
-
bottom: Int,
|
|
65
|
-
text: CharSequence?,
|
|
66
|
-
start: Int,
|
|
67
|
-
end: Int,
|
|
68
|
-
first: Boolean,
|
|
69
|
-
layout: Layout?,
|
|
70
|
-
) {
|
|
71
|
-
// Essential check from original: only the deepest span draws to prevent over-rendering background
|
|
72
|
-
if (shouldSkipDrawing(text, start)) return
|
|
73
|
-
|
|
74
|
-
val borderPaint = configureBorderPaint()
|
|
75
|
-
val radius = blockquoteStyle.borderRadius
|
|
76
|
-
val spanned = text as? Spanned
|
|
77
|
-
|
|
78
|
-
if (spanned == null) {
|
|
79
|
-
drawBorders(c, x, dir, top, bottom, borderPaint)
|
|
80
|
-
return
|
|
81
|
-
}
|
|
82
|
-
|
|
83
|
-
val rootSpan = spanAtMinDepth(spanned, start)
|
|
84
|
-
val clipToRoot =
|
|
85
|
-
radius > 0f && boxRight > boxLeft && rootSpan != null && isBoundaryLine(spanned, start, end, rootSpan)
|
|
86
|
-
|
|
87
|
-
val padding = blockquoteStyle.padding
|
|
88
|
-
var topInset = 0f
|
|
89
|
-
var bottomInset = 0f
|
|
90
|
-
|
|
91
|
-
for (level in 0..depth) {
|
|
92
|
-
val borderX = x + (levelSpacing * level * dir)
|
|
93
|
-
val borderRight = borderX + (blockquoteStyle.borderWidth * dir)
|
|
94
|
-
val stripeLeft = minOf(borderX, borderRight)
|
|
95
|
-
val stripeRight = maxOf(borderX, borderRight)
|
|
96
|
-
val stripeTop = top.toFloat() + topInset
|
|
97
|
-
val stripeBottom = bottom.toFloat() - bottomInset
|
|
98
|
-
|
|
99
|
-
val levelSpan = if (level == 0) rootSpan else spanAtDepth(spanned, start, level)
|
|
100
|
-
val clipToOwn =
|
|
101
|
-
radius > 0f && level > 0 && levelSpan != null && isBoundaryLine(spanned, start, end, levelSpan)
|
|
102
|
-
|
|
103
|
-
if (!clipToRoot && !clipToOwn) {
|
|
104
|
-
c.drawRect(stripeLeft, stripeTop, stripeRight, stripeBottom, borderPaint)
|
|
105
|
-
} else {
|
|
106
|
-
c.withSave {
|
|
107
|
-
if (clipToRoot) {
|
|
108
|
-
buildBoundaryPath(spanned, start, end, rootSpan!!, boxLeft, top.toFloat(), boxRight, bottom.toFloat())
|
|
109
|
-
clipPath(path)
|
|
110
|
-
}
|
|
111
|
-
if (clipToOwn) {
|
|
112
|
-
val clipLeft = if (dir >= 0) stripeLeft else boxLeft
|
|
113
|
-
val clipRight = if (dir >= 0) boxRight else stripeRight
|
|
114
|
-
buildBoundaryPath(spanned, start, end, levelSpan!!, clipLeft, stripeTop, clipRight, stripeBottom)
|
|
115
|
-
clipPath(path)
|
|
116
|
-
}
|
|
117
|
-
drawRect(stripeLeft, stripeTop, stripeRight, stripeBottom, borderPaint)
|
|
118
|
-
}
|
|
119
|
-
}
|
|
120
|
-
|
|
121
|
-
if (padding > 0 && levelSpan != null) {
|
|
122
|
-
if (start == spanned.getSpanStart(levelSpan)) topInset += padding
|
|
123
|
-
if (isLastLineOf(spanned, end, levelSpan)) bottomInset += padding
|
|
124
|
-
}
|
|
125
|
-
}
|
|
126
|
-
}
|
|
127
|
-
|
|
128
|
-
override fun drawBackground(
|
|
129
|
-
canvas: Canvas,
|
|
130
|
-
paint: Paint,
|
|
131
|
-
left: Int,
|
|
132
|
-
right: Int,
|
|
133
|
-
top: Int,
|
|
134
|
-
baseline: Int,
|
|
135
|
-
bottom: Int,
|
|
136
|
-
text: CharSequence,
|
|
137
|
-
start: Int,
|
|
138
|
-
end: Int,
|
|
139
|
-
lineNum: Int,
|
|
140
|
-
) {
|
|
141
|
-
if (shouldSkipDrawing(text, start)) return
|
|
142
|
-
|
|
143
|
-
boxLeft = left.toFloat()
|
|
144
|
-
boxRight = right.toFloat()
|
|
145
|
-
|
|
146
|
-
val bgColor = blockquoteStyle.backgroundColor?.takeIf { it != Color.TRANSPARENT } ?: return
|
|
147
|
-
val backgroundPaint = configureBackgroundPaint(bgColor)
|
|
148
|
-
val radius = blockquoteStyle.borderRadius
|
|
149
|
-
val rootSpan = (text as? Spanned)?.let { spanAtMinDepth(it, start) }
|
|
150
|
-
|
|
151
|
-
if (radius <= 0f || rootSpan == null) {
|
|
152
|
-
canvas.drawRect(left.toFloat(), top.toFloat(), right.toFloat(), bottom.toFloat(), backgroundPaint)
|
|
153
|
-
return
|
|
154
|
-
}
|
|
155
|
-
|
|
156
|
-
buildBoundaryPath(text as Spanned, start, end, rootSpan, left.toFloat(), top.toFloat(), right.toFloat(), bottom.toFloat())
|
|
157
|
-
canvas.drawPath(path, backgroundPaint)
|
|
158
|
-
}
|
|
159
|
-
|
|
160
|
-
private fun drawBorders(
|
|
161
|
-
c: Canvas,
|
|
162
|
-
x: Int,
|
|
163
|
-
dir: Int,
|
|
164
|
-
top: Int,
|
|
165
|
-
bottom: Int,
|
|
166
|
-
borderPaint: Paint,
|
|
167
|
-
) {
|
|
168
|
-
val borderTop = top.toFloat()
|
|
169
|
-
val borderBottom = bottom.toFloat()
|
|
170
|
-
|
|
171
|
-
for (level in 0..depth) {
|
|
172
|
-
val borderX = x + (levelSpacing * level * dir)
|
|
173
|
-
val borderRight = borderX + (blockquoteStyle.borderWidth * dir)
|
|
174
|
-
c.drawRect(minOf(borderX, borderRight), borderTop, maxOf(borderX, borderRight), borderBottom, borderPaint)
|
|
175
|
-
}
|
|
176
|
-
}
|
|
177
|
-
|
|
178
|
-
@SuppressLint("WrongConstant") // Result of mask is always valid: 0, 1, 2, or 3
|
|
179
|
-
private fun applyTextStyle(tp: TextPaint) {
|
|
180
|
-
tp.textSize = blockStyle.fontSize
|
|
181
|
-
val preserved = (tp.typeface?.style ?: 0) and BOLD_ITALIC_MASK
|
|
182
|
-
tp.applyBlockStyleFont(blockStyle, context)
|
|
183
|
-
if (preserved != 0) {
|
|
184
|
-
tp.typeface = Typeface.create(tp.typeface ?: Typeface.DEFAULT, preserved)
|
|
185
|
-
}
|
|
186
|
-
tp.applyColorPreserving(blockStyle.color, *styleCache.colorsToPreserve)
|
|
187
|
-
}
|
|
188
|
-
|
|
189
|
-
companion object {
|
|
190
|
-
private const val BOLD_ITALIC_MASK = Typeface.BOLD or Typeface.ITALIC
|
|
191
|
-
|
|
192
|
-
private val sharedBorderPaint = Paint(Paint.ANTI_ALIAS_FLAG).apply { style = Paint.Style.FILL }
|
|
193
|
-
private val sharedBackgroundPaint = Paint(Paint.ANTI_ALIAS_FLAG).apply { style = Paint.Style.FILL }
|
|
194
|
-
}
|
|
195
|
-
|
|
196
|
-
private fun configureBorderPaint(): Paint =
|
|
197
|
-
sharedBorderPaint.apply {
|
|
198
|
-
color = blockquoteStyle.borderColor
|
|
199
|
-
}
|
|
200
|
-
|
|
201
|
-
private fun configureBackgroundPaint(bgColor: Int): Paint =
|
|
202
|
-
sharedBackgroundPaint.apply {
|
|
203
|
-
color = bgColor
|
|
204
|
-
}
|
|
205
|
-
|
|
206
|
-
private fun spansAt(
|
|
207
|
-
text: Spanned,
|
|
208
|
-
start: Int,
|
|
209
|
-
): Array<BlockquoteSpan> {
|
|
210
|
-
if (cachedText !== text) {
|
|
211
|
-
cachedText = text
|
|
212
|
-
cachedSpansByPosition.clear()
|
|
213
|
-
}
|
|
214
|
-
return cachedSpansByPosition.getOrPut(start) {
|
|
215
|
-
text.getSpans(start, start + 1, BlockquoteSpan::class.java)
|
|
216
|
-
}
|
|
217
|
-
}
|
|
218
|
-
|
|
219
|
-
private fun shouldSkipDrawing(
|
|
220
|
-
text: CharSequence?,
|
|
221
|
-
start: Int,
|
|
222
|
-
): Boolean {
|
|
223
|
-
if (text !is Spanned) return false
|
|
224
|
-
val maxDepth = spansAt(text, start).maxOfOrNull { it.depth } ?: -1
|
|
225
|
-
return maxDepth > depth
|
|
226
|
-
}
|
|
227
|
-
|
|
228
|
-
private fun spanAtMinDepth(
|
|
229
|
-
text: Spanned,
|
|
230
|
-
start: Int,
|
|
231
|
-
): BlockquoteSpan? = spansAt(text, start).minByOrNull { it.depth }
|
|
232
|
-
|
|
233
|
-
private fun spanAtDepth(
|
|
234
|
-
text: Spanned,
|
|
235
|
-
start: Int,
|
|
236
|
-
level: Int,
|
|
237
|
-
): BlockquoteSpan? = spansAt(text, start).firstOrNull { it.depth == level }
|
|
238
|
-
|
|
239
|
-
/**
|
|
240
|
-
* The span range can include trailing '\n'(s) that form no visible line (e.g. a
|
|
241
|
-
* paragraph break closing the quote), so the last drawn line ends before getSpanEnd;
|
|
242
|
-
* this compares against the end of visible content instead.
|
|
243
|
-
*/
|
|
244
|
-
private fun isLastLineOf(
|
|
245
|
-
text: Spanned,
|
|
246
|
-
lineEnd: Int,
|
|
247
|
-
box: BlockquoteSpan,
|
|
248
|
-
): Boolean {
|
|
249
|
-
var boxEnd = text.getSpanEnd(box)
|
|
250
|
-
while (boxEnd > 0 && text[boxEnd - 1] == '\n') {
|
|
251
|
-
boxEnd--
|
|
252
|
-
}
|
|
253
|
-
return lineEnd >= boxEnd
|
|
254
|
-
}
|
|
255
|
-
|
|
256
|
-
private fun isBoundaryLine(
|
|
257
|
-
text: Spanned,
|
|
258
|
-
lineStart: Int,
|
|
259
|
-
lineEnd: Int,
|
|
260
|
-
box: BlockquoteSpan,
|
|
261
|
-
): Boolean {
|
|
262
|
-
val boxStart = text.getSpanStart(box)
|
|
263
|
-
val boxEnd = text.getSpanEnd(box)
|
|
264
|
-
if (boxStart !in 0 until boxEnd) return false
|
|
265
|
-
return lineStart == boxStart || isLastLineOf(text, lineEnd, box)
|
|
266
|
-
}
|
|
267
|
-
|
|
268
|
-
private fun buildBoundaryPath(
|
|
269
|
-
text: Spanned,
|
|
270
|
-
lineStart: Int,
|
|
271
|
-
lineEnd: Int,
|
|
272
|
-
box: BlockquoteSpan,
|
|
273
|
-
left: Float,
|
|
274
|
-
top: Float,
|
|
275
|
-
right: Float,
|
|
276
|
-
bottom: Float,
|
|
277
|
-
) {
|
|
278
|
-
val boxStart = text.getSpanStart(box)
|
|
279
|
-
|
|
280
|
-
val isFirstLine = lineStart == boxStart
|
|
281
|
-
val isLastLine = isLastLineOf(text, lineEnd, box)
|
|
282
|
-
|
|
283
|
-
val radius = blockquoteStyle.borderRadius
|
|
284
|
-
radiiArray.fill(0f)
|
|
285
|
-
if (isFirstLine) {
|
|
286
|
-
radiiArray[0] = radius
|
|
287
|
-
radiiArray[1] = radius // Top-Left
|
|
288
|
-
radiiArray[2] = radius
|
|
289
|
-
radiiArray[3] = radius // Top-Right
|
|
290
|
-
}
|
|
291
|
-
if (isLastLine) {
|
|
292
|
-
radiiArray[4] = radius
|
|
293
|
-
radiiArray[5] = radius // Bottom-Right
|
|
294
|
-
radiiArray[6] = radius
|
|
295
|
-
radiiArray[7] = radius // Bottom-Left
|
|
296
|
-
}
|
|
297
|
-
|
|
298
|
-
rect.set(left, top, right, bottom)
|
|
299
|
-
path.reset()
|
|
300
|
-
path.addRoundRect(rect, radiiArray, Path.Direction.CW)
|
|
301
|
-
}
|
|
302
|
-
}
|
|
1
|
+
package com.renderrichtext.spans
|
|
2
|
+
|
|
3
|
+
import android.annotation.SuppressLint
|
|
4
|
+
import android.content.Context
|
|
5
|
+
import android.graphics.Canvas
|
|
6
|
+
import android.graphics.Color
|
|
7
|
+
import android.graphics.Paint
|
|
8
|
+
import android.graphics.Path
|
|
9
|
+
import android.graphics.RectF
|
|
10
|
+
import android.graphics.Typeface
|
|
11
|
+
import android.text.Layout
|
|
12
|
+
import android.text.Spanned
|
|
13
|
+
import android.text.TextPaint
|
|
14
|
+
import android.text.style.LeadingMarginSpan
|
|
15
|
+
import android.text.style.LineBackgroundSpan
|
|
16
|
+
import android.text.style.MetricAffectingSpan
|
|
17
|
+
import androidx.core.graphics.withSave
|
|
18
|
+
import com.renderrichtext.renderer.BlockStyle
|
|
19
|
+
import com.renderrichtext.renderer.SpanStyleCache
|
|
20
|
+
import com.renderrichtext.styles.BlockquoteStyle
|
|
21
|
+
import com.renderrichtext.utils.text.extensions.applyBlockStyleFont
|
|
22
|
+
import com.renderrichtext.utils.text.extensions.applyColorPreserving
|
|
23
|
+
|
|
24
|
+
class BlockquoteSpan(
|
|
25
|
+
private val blockquoteStyle: BlockquoteStyle,
|
|
26
|
+
val depth: Int,
|
|
27
|
+
private val context: Context,
|
|
28
|
+
private val styleCache: SpanStyleCache,
|
|
29
|
+
) : MetricAffectingSpan(),
|
|
30
|
+
LeadingMarginSpan,
|
|
31
|
+
LineBackgroundSpan {
|
|
32
|
+
private val levelSpacing: Float = blockquoteStyle.borderWidth + blockquoteStyle.gapWidth
|
|
33
|
+
private val blockStyle =
|
|
34
|
+
BlockStyle(
|
|
35
|
+
fontSize = blockquoteStyle.fontSize,
|
|
36
|
+
fontFamily = blockquoteStyle.fontFamily,
|
|
37
|
+
fontWeight = blockquoteStyle.fontWeight,
|
|
38
|
+
color = blockquoteStyle.color,
|
|
39
|
+
)
|
|
40
|
+
|
|
41
|
+
// Cache for shouldSkipDrawing to avoid repeated getSpans() calls during draw passes
|
|
42
|
+
private var cachedText: CharSequence? = null
|
|
43
|
+
private var cachedSpansByPosition = mutableMapOf<Int, Array<BlockquoteSpan>>()
|
|
44
|
+
private var boxLeft = 0f
|
|
45
|
+
private var boxRight = 0f
|
|
46
|
+
|
|
47
|
+
private val path = Path()
|
|
48
|
+
private val rect = RectF()
|
|
49
|
+
private val radiiArray = FloatArray(8)
|
|
50
|
+
|
|
51
|
+
override fun updateMeasureState(tp: TextPaint) = applyTextStyle(tp)
|
|
52
|
+
|
|
53
|
+
override fun updateDrawState(tp: TextPaint) = applyTextStyle(tp)
|
|
54
|
+
|
|
55
|
+
override fun getLeadingMargin(first: Boolean): Int = levelSpacing.toInt()
|
|
56
|
+
|
|
57
|
+
override fun drawLeadingMargin(
|
|
58
|
+
c: Canvas,
|
|
59
|
+
p: Paint,
|
|
60
|
+
x: Int,
|
|
61
|
+
dir: Int,
|
|
62
|
+
top: Int,
|
|
63
|
+
baseline: Int,
|
|
64
|
+
bottom: Int,
|
|
65
|
+
text: CharSequence?,
|
|
66
|
+
start: Int,
|
|
67
|
+
end: Int,
|
|
68
|
+
first: Boolean,
|
|
69
|
+
layout: Layout?,
|
|
70
|
+
) {
|
|
71
|
+
// Essential check from original: only the deepest span draws to prevent over-rendering background
|
|
72
|
+
if (shouldSkipDrawing(text, start)) return
|
|
73
|
+
|
|
74
|
+
val borderPaint = configureBorderPaint()
|
|
75
|
+
val radius = blockquoteStyle.borderRadius
|
|
76
|
+
val spanned = text as? Spanned
|
|
77
|
+
|
|
78
|
+
if (spanned == null) {
|
|
79
|
+
drawBorders(c, x, dir, top, bottom, borderPaint)
|
|
80
|
+
return
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
val rootSpan = spanAtMinDepth(spanned, start)
|
|
84
|
+
val clipToRoot =
|
|
85
|
+
radius > 0f && boxRight > boxLeft && rootSpan != null && isBoundaryLine(spanned, start, end, rootSpan)
|
|
86
|
+
|
|
87
|
+
val padding = blockquoteStyle.padding
|
|
88
|
+
var topInset = 0f
|
|
89
|
+
var bottomInset = 0f
|
|
90
|
+
|
|
91
|
+
for (level in 0..depth) {
|
|
92
|
+
val borderX = x + (levelSpacing * level * dir)
|
|
93
|
+
val borderRight = borderX + (blockquoteStyle.borderWidth * dir)
|
|
94
|
+
val stripeLeft = minOf(borderX, borderRight)
|
|
95
|
+
val stripeRight = maxOf(borderX, borderRight)
|
|
96
|
+
val stripeTop = top.toFloat() + topInset
|
|
97
|
+
val stripeBottom = bottom.toFloat() - bottomInset
|
|
98
|
+
|
|
99
|
+
val levelSpan = if (level == 0) rootSpan else spanAtDepth(spanned, start, level)
|
|
100
|
+
val clipToOwn =
|
|
101
|
+
radius > 0f && level > 0 && levelSpan != null && isBoundaryLine(spanned, start, end, levelSpan)
|
|
102
|
+
|
|
103
|
+
if (!clipToRoot && !clipToOwn) {
|
|
104
|
+
c.drawRect(stripeLeft, stripeTop, stripeRight, stripeBottom, borderPaint)
|
|
105
|
+
} else {
|
|
106
|
+
c.withSave {
|
|
107
|
+
if (clipToRoot) {
|
|
108
|
+
buildBoundaryPath(spanned, start, end, rootSpan!!, boxLeft, top.toFloat(), boxRight, bottom.toFloat())
|
|
109
|
+
clipPath(path)
|
|
110
|
+
}
|
|
111
|
+
if (clipToOwn) {
|
|
112
|
+
val clipLeft = if (dir >= 0) stripeLeft else boxLeft
|
|
113
|
+
val clipRight = if (dir >= 0) boxRight else stripeRight
|
|
114
|
+
buildBoundaryPath(spanned, start, end, levelSpan!!, clipLeft, stripeTop, clipRight, stripeBottom)
|
|
115
|
+
clipPath(path)
|
|
116
|
+
}
|
|
117
|
+
drawRect(stripeLeft, stripeTop, stripeRight, stripeBottom, borderPaint)
|
|
118
|
+
}
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
if (padding > 0 && levelSpan != null) {
|
|
122
|
+
if (start == spanned.getSpanStart(levelSpan)) topInset += padding
|
|
123
|
+
if (isLastLineOf(spanned, end, levelSpan)) bottomInset += padding
|
|
124
|
+
}
|
|
125
|
+
}
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
override fun drawBackground(
|
|
129
|
+
canvas: Canvas,
|
|
130
|
+
paint: Paint,
|
|
131
|
+
left: Int,
|
|
132
|
+
right: Int,
|
|
133
|
+
top: Int,
|
|
134
|
+
baseline: Int,
|
|
135
|
+
bottom: Int,
|
|
136
|
+
text: CharSequence,
|
|
137
|
+
start: Int,
|
|
138
|
+
end: Int,
|
|
139
|
+
lineNum: Int,
|
|
140
|
+
) {
|
|
141
|
+
if (shouldSkipDrawing(text, start)) return
|
|
142
|
+
|
|
143
|
+
boxLeft = left.toFloat()
|
|
144
|
+
boxRight = right.toFloat()
|
|
145
|
+
|
|
146
|
+
val bgColor = blockquoteStyle.backgroundColor?.takeIf { it != Color.TRANSPARENT } ?: return
|
|
147
|
+
val backgroundPaint = configureBackgroundPaint(bgColor)
|
|
148
|
+
val radius = blockquoteStyle.borderRadius
|
|
149
|
+
val rootSpan = (text as? Spanned)?.let { spanAtMinDepth(it, start) }
|
|
150
|
+
|
|
151
|
+
if (radius <= 0f || rootSpan == null) {
|
|
152
|
+
canvas.drawRect(left.toFloat(), top.toFloat(), right.toFloat(), bottom.toFloat(), backgroundPaint)
|
|
153
|
+
return
|
|
154
|
+
}
|
|
155
|
+
|
|
156
|
+
buildBoundaryPath(text as Spanned, start, end, rootSpan, left.toFloat(), top.toFloat(), right.toFloat(), bottom.toFloat())
|
|
157
|
+
canvas.drawPath(path, backgroundPaint)
|
|
158
|
+
}
|
|
159
|
+
|
|
160
|
+
private fun drawBorders(
|
|
161
|
+
c: Canvas,
|
|
162
|
+
x: Int,
|
|
163
|
+
dir: Int,
|
|
164
|
+
top: Int,
|
|
165
|
+
bottom: Int,
|
|
166
|
+
borderPaint: Paint,
|
|
167
|
+
) {
|
|
168
|
+
val borderTop = top.toFloat()
|
|
169
|
+
val borderBottom = bottom.toFloat()
|
|
170
|
+
|
|
171
|
+
for (level in 0..depth) {
|
|
172
|
+
val borderX = x + (levelSpacing * level * dir)
|
|
173
|
+
val borderRight = borderX + (blockquoteStyle.borderWidth * dir)
|
|
174
|
+
c.drawRect(minOf(borderX, borderRight), borderTop, maxOf(borderX, borderRight), borderBottom, borderPaint)
|
|
175
|
+
}
|
|
176
|
+
}
|
|
177
|
+
|
|
178
|
+
@SuppressLint("WrongConstant") // Result of mask is always valid: 0, 1, 2, or 3
|
|
179
|
+
private fun applyTextStyle(tp: TextPaint) {
|
|
180
|
+
tp.textSize = blockStyle.fontSize
|
|
181
|
+
val preserved = (tp.typeface?.style ?: 0) and BOLD_ITALIC_MASK
|
|
182
|
+
tp.applyBlockStyleFont(blockStyle, context)
|
|
183
|
+
if (preserved != 0) {
|
|
184
|
+
tp.typeface = Typeface.create(tp.typeface ?: Typeface.DEFAULT, preserved)
|
|
185
|
+
}
|
|
186
|
+
tp.applyColorPreserving(blockStyle.color, *styleCache.colorsToPreserve)
|
|
187
|
+
}
|
|
188
|
+
|
|
189
|
+
companion object {
|
|
190
|
+
private const val BOLD_ITALIC_MASK = Typeface.BOLD or Typeface.ITALIC
|
|
191
|
+
|
|
192
|
+
private val sharedBorderPaint = Paint(Paint.ANTI_ALIAS_FLAG).apply { style = Paint.Style.FILL }
|
|
193
|
+
private val sharedBackgroundPaint = Paint(Paint.ANTI_ALIAS_FLAG).apply { style = Paint.Style.FILL }
|
|
194
|
+
}
|
|
195
|
+
|
|
196
|
+
private fun configureBorderPaint(): Paint =
|
|
197
|
+
sharedBorderPaint.apply {
|
|
198
|
+
color = blockquoteStyle.borderColor
|
|
199
|
+
}
|
|
200
|
+
|
|
201
|
+
private fun configureBackgroundPaint(bgColor: Int): Paint =
|
|
202
|
+
sharedBackgroundPaint.apply {
|
|
203
|
+
color = bgColor
|
|
204
|
+
}
|
|
205
|
+
|
|
206
|
+
private fun spansAt(
|
|
207
|
+
text: Spanned,
|
|
208
|
+
start: Int,
|
|
209
|
+
): Array<BlockquoteSpan> {
|
|
210
|
+
if (cachedText !== text) {
|
|
211
|
+
cachedText = text
|
|
212
|
+
cachedSpansByPosition.clear()
|
|
213
|
+
}
|
|
214
|
+
return cachedSpansByPosition.getOrPut(start) {
|
|
215
|
+
text.getSpans(start, start + 1, BlockquoteSpan::class.java)
|
|
216
|
+
}
|
|
217
|
+
}
|
|
218
|
+
|
|
219
|
+
private fun shouldSkipDrawing(
|
|
220
|
+
text: CharSequence?,
|
|
221
|
+
start: Int,
|
|
222
|
+
): Boolean {
|
|
223
|
+
if (text !is Spanned) return false
|
|
224
|
+
val maxDepth = spansAt(text, start).maxOfOrNull { it.depth } ?: -1
|
|
225
|
+
return maxDepth > depth
|
|
226
|
+
}
|
|
227
|
+
|
|
228
|
+
private fun spanAtMinDepth(
|
|
229
|
+
text: Spanned,
|
|
230
|
+
start: Int,
|
|
231
|
+
): BlockquoteSpan? = spansAt(text, start).minByOrNull { it.depth }
|
|
232
|
+
|
|
233
|
+
private fun spanAtDepth(
|
|
234
|
+
text: Spanned,
|
|
235
|
+
start: Int,
|
|
236
|
+
level: Int,
|
|
237
|
+
): BlockquoteSpan? = spansAt(text, start).firstOrNull { it.depth == level }
|
|
238
|
+
|
|
239
|
+
/**
|
|
240
|
+
* The span range can include trailing '\n'(s) that form no visible line (e.g. a
|
|
241
|
+
* paragraph break closing the quote), so the last drawn line ends before getSpanEnd;
|
|
242
|
+
* this compares against the end of visible content instead.
|
|
243
|
+
*/
|
|
244
|
+
private fun isLastLineOf(
|
|
245
|
+
text: Spanned,
|
|
246
|
+
lineEnd: Int,
|
|
247
|
+
box: BlockquoteSpan,
|
|
248
|
+
): Boolean {
|
|
249
|
+
var boxEnd = text.getSpanEnd(box)
|
|
250
|
+
while (boxEnd > 0 && text[boxEnd - 1] == '\n') {
|
|
251
|
+
boxEnd--
|
|
252
|
+
}
|
|
253
|
+
return lineEnd >= boxEnd
|
|
254
|
+
}
|
|
255
|
+
|
|
256
|
+
private fun isBoundaryLine(
|
|
257
|
+
text: Spanned,
|
|
258
|
+
lineStart: Int,
|
|
259
|
+
lineEnd: Int,
|
|
260
|
+
box: BlockquoteSpan,
|
|
261
|
+
): Boolean {
|
|
262
|
+
val boxStart = text.getSpanStart(box)
|
|
263
|
+
val boxEnd = text.getSpanEnd(box)
|
|
264
|
+
if (boxStart !in 0 until boxEnd) return false
|
|
265
|
+
return lineStart == boxStart || isLastLineOf(text, lineEnd, box)
|
|
266
|
+
}
|
|
267
|
+
|
|
268
|
+
private fun buildBoundaryPath(
|
|
269
|
+
text: Spanned,
|
|
270
|
+
lineStart: Int,
|
|
271
|
+
lineEnd: Int,
|
|
272
|
+
box: BlockquoteSpan,
|
|
273
|
+
left: Float,
|
|
274
|
+
top: Float,
|
|
275
|
+
right: Float,
|
|
276
|
+
bottom: Float,
|
|
277
|
+
) {
|
|
278
|
+
val boxStart = text.getSpanStart(box)
|
|
279
|
+
|
|
280
|
+
val isFirstLine = lineStart == boxStart
|
|
281
|
+
val isLastLine = isLastLineOf(text, lineEnd, box)
|
|
282
|
+
|
|
283
|
+
val radius = blockquoteStyle.borderRadius
|
|
284
|
+
radiiArray.fill(0f)
|
|
285
|
+
if (isFirstLine) {
|
|
286
|
+
radiiArray[0] = radius
|
|
287
|
+
radiiArray[1] = radius // Top-Left
|
|
288
|
+
radiiArray[2] = radius
|
|
289
|
+
radiiArray[3] = radius // Top-Right
|
|
290
|
+
}
|
|
291
|
+
if (isLastLine) {
|
|
292
|
+
radiiArray[4] = radius
|
|
293
|
+
radiiArray[5] = radius // Bottom-Right
|
|
294
|
+
radiiArray[6] = radius
|
|
295
|
+
radiiArray[7] = radius // Bottom-Left
|
|
296
|
+
}
|
|
297
|
+
|
|
298
|
+
rect.set(left, top, right, bottom)
|
|
299
|
+
path.reset()
|
|
300
|
+
path.addRoundRect(rect, radiiArray, Path.Direction.CW)
|
|
301
|
+
}
|
|
302
|
+
}
|