@mathers101/react-native-render-rich-text 0.0.0-stage → 0.1.9
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 -0
- package/README.md +140 -3
- package/ReactNativeRenderRichText.podspec +23 -0
- package/android/build.gradle +86 -0
- package/android/consumer-rules.pro +3 -0
- package/android/src/main/AndroidManifest.xml +2 -0
- package/android/src/main/cpp/jni-adapter.cpp +191 -0
- package/android/src/main/java/com/renderrichtext/EnrichedTiptapText.kt +673 -0
- package/android/src/main/java/com/renderrichtext/EnrichedTiptapTextLayoutManager.kt +24 -0
- package/android/src/main/java/com/renderrichtext/EnrichedTiptapTextManager.kt +405 -0
- package/android/src/main/java/com/renderrichtext/EnrichedTiptapTextPackage.kt +13 -0
- package/android/src/main/java/com/renderrichtext/MeasurementStore.kt +644 -0
- package/android/src/main/java/com/renderrichtext/accessibility/AccessibilityLabels.kt +17 -0
- package/android/src/main/java/com/renderrichtext/accessibility/AccessibleTiptapTextView.kt +112 -0
- package/android/src/main/java/com/renderrichtext/accessibility/TiptapAccessibilityHelper.kt +576 -0
- package/android/src/main/java/com/renderrichtext/events/CodeBlockPressEvent.kt +24 -0
- package/android/src/main/java/com/renderrichtext/events/ContextMenuItemPressEvent.kt +28 -0
- package/android/src/main/java/com/renderrichtext/events/CopyPressEvent.kt +24 -0
- package/android/src/main/java/com/renderrichtext/events/FactoidPressEvent.kt +23 -0
- package/android/src/main/java/com/renderrichtext/events/ImagePressEvent.kt +25 -0
- package/android/src/main/java/com/renderrichtext/events/LatexErrorEvent.kt +29 -0
- package/android/src/main/java/com/renderrichtext/events/LinkLongPressEvent.kt +23 -0
- package/android/src/main/java/com/renderrichtext/events/LinkPressEvent.kt +23 -0
- package/android/src/main/java/com/renderrichtext/events/MentionLongPressEvent.kt +25 -0
- package/android/src/main/java/com/renderrichtext/events/MentionPressEvent.kt +25 -0
- package/android/src/main/java/com/renderrichtext/events/TaskListItemPressEvent.kt +26 -0
- package/android/src/main/java/com/renderrichtext/math/LatexErrorReporter.kt +9 -0
- package/android/src/main/java/com/renderrichtext/parser/Parser.kt +59 -0
- package/android/src/main/java/com/renderrichtext/parser/TextLinkMatching.kt +35 -0
- package/android/src/main/java/com/renderrichtext/parser/TiptapASTNode.kt +69 -0
- package/android/src/main/java/com/renderrichtext/renderer/BaselineShiftRenderer.kt +45 -0
- package/android/src/main/java/com/renderrichtext/renderer/BlankLineRenderer.kt +39 -0
- package/android/src/main/java/com/renderrichtext/renderer/BlockStyleContext.kt +181 -0
- package/android/src/main/java/com/renderrichtext/renderer/BlockquoteRenderer.kt +243 -0
- package/android/src/main/java/com/renderrichtext/renderer/BlockquoteTextRenderer.kt +56 -0
- package/android/src/main/java/com/renderrichtext/renderer/CodeBlockRenderer.kt +135 -0
- package/android/src/main/java/com/renderrichtext/renderer/CodeRenderer.kt +37 -0
- package/android/src/main/java/com/renderrichtext/renderer/EmphasisRenderer.kt +28 -0
- package/android/src/main/java/com/renderrichtext/renderer/FactoidRenderer.kt +97 -0
- package/android/src/main/java/com/renderrichtext/renderer/HeadingRenderer.kt +81 -0
- package/android/src/main/java/com/renderrichtext/renderer/HighlightRenderer.kt +26 -0
- package/android/src/main/java/com/renderrichtext/renderer/LineBreakRenderer.kt +17 -0
- package/android/src/main/java/com/renderrichtext/renderer/LinkRenderer.kt +90 -0
- package/android/src/main/java/com/renderrichtext/renderer/ListContextManager.kt +109 -0
- package/android/src/main/java/com/renderrichtext/renderer/ListItemRenderer.kt +211 -0
- package/android/src/main/java/com/renderrichtext/renderer/ListRenderer.kt +133 -0
- package/android/src/main/java/com/renderrichtext/renderer/MentionRenderer.kt +85 -0
- package/android/src/main/java/com/renderrichtext/renderer/NodeRenderer.kt +207 -0
- package/android/src/main/java/com/renderrichtext/renderer/ParagraphRenderer.kt +91 -0
- package/android/src/main/java/com/renderrichtext/renderer/Renderer.kt +148 -0
- package/android/src/main/java/com/renderrichtext/renderer/SoftBreakRenderer.kt +17 -0
- package/android/src/main/java/com/renderrichtext/renderer/SpanStyleCache.kt +143 -0
- package/android/src/main/java/com/renderrichtext/renderer/StrikethroughRenderer.kt +28 -0
- package/android/src/main/java/com/renderrichtext/renderer/StrongRenderer.kt +28 -0
- package/android/src/main/java/com/renderrichtext/renderer/TextRenderer.kt +31 -0
- package/android/src/main/java/com/renderrichtext/renderer/ThematicBreakRenderer.kt +46 -0
- package/android/src/main/java/com/renderrichtext/renderer/UnderlineRenderer.kt +28 -0
- package/android/src/main/java/com/renderrichtext/spans/BaseListSpan.kt +164 -0
- package/android/src/main/java/com/renderrichtext/spans/BaselineShiftSpan.kt +27 -0
- package/android/src/main/java/com/renderrichtext/spans/BlockquoteSpan.kt +302 -0
- package/android/src/main/java/com/renderrichtext/spans/CodeBackgroundSpan.kt +205 -0
- package/android/src/main/java/com/renderrichtext/spans/CodeBlockSpan.kt +216 -0
- package/android/src/main/java/com/renderrichtext/spans/CodeSpan.kt +32 -0
- package/android/src/main/java/com/renderrichtext/spans/EmphasisSpan.kt +42 -0
- package/android/src/main/java/com/renderrichtext/spans/FactoidBackgroundSpan.kt +265 -0
- package/android/src/main/java/com/renderrichtext/spans/FactoidPaddingSpan.kt +258 -0
- package/android/src/main/java/com/renderrichtext/spans/FactoidSpan.kt +32 -0
- package/android/src/main/java/com/renderrichtext/spans/FadeInSpan.kt +29 -0
- package/android/src/main/java/com/renderrichtext/spans/HeadingSpan.kt +38 -0
- package/android/src/main/java/com/renderrichtext/spans/HighlightSpan.kt +80 -0
- package/android/src/main/java/com/renderrichtext/spans/ImageSpan.kt +481 -0
- package/android/src/main/java/com/renderrichtext/spans/InlineBackgroundGeometry.kt +42 -0
- package/android/src/main/java/com/renderrichtext/spans/LineHeightSpan.kt +39 -0
- package/android/src/main/java/com/renderrichtext/spans/LinkPillIconCache.kt +154 -0
- package/android/src/main/java/com/renderrichtext/spans/LinkPillSpan.kt +381 -0
- package/android/src/main/java/com/renderrichtext/spans/LinkSpan.kt +68 -0
- package/android/src/main/java/com/renderrichtext/spans/ListItemSpacingSpan.kt +33 -0
- package/android/src/main/java/com/renderrichtext/spans/ListMarkerAnchorSpan.kt +38 -0
- package/android/src/main/java/com/renderrichtext/spans/MarginBottomSpan.kt +76 -0
- package/android/src/main/java/com/renderrichtext/spans/MentionChipSpan.kt +132 -0
- package/android/src/main/java/com/renderrichtext/spans/MentionSpan.kt +46 -0
- package/android/src/main/java/com/renderrichtext/spans/OrderedListSpan.kt +127 -0
- package/android/src/main/java/com/renderrichtext/spans/SpoilerSpan.kt +33 -0
- package/android/src/main/java/com/renderrichtext/spans/StrikethroughSpan.kt +12 -0
- package/android/src/main/java/com/renderrichtext/spans/StrongSpan.kt +39 -0
- package/android/src/main/java/com/renderrichtext/spans/TaskListSpan.kt +143 -0
- package/android/src/main/java/com/renderrichtext/spans/TextSpan.kt +26 -0
- package/android/src/main/java/com/renderrichtext/spans/ThematicBreakSpan.kt +69 -0
- package/android/src/main/java/com/renderrichtext/spans/UnorderedListSpan.kt +96 -0
- package/android/src/main/java/com/renderrichtext/spoiler/SpoilerStubs.kt +46 -0
- package/android/src/main/java/com/renderrichtext/styles/BaseBlockStyle.kt +11 -0
- package/android/src/main/java/com/renderrichtext/styles/BlockquoteStyle.kt +83 -0
- package/android/src/main/java/com/renderrichtext/styles/CodeBlockStyle.kt +80 -0
- package/android/src/main/java/com/renderrichtext/styles/CodeStyle.kt +26 -0
- package/android/src/main/java/com/renderrichtext/styles/EmphasisStyle.kt +21 -0
- package/android/src/main/java/com/renderrichtext/styles/FactoidStyle.kt +21 -0
- package/android/src/main/java/com/renderrichtext/styles/HeadingStyle.kt +33 -0
- package/android/src/main/java/com/renderrichtext/styles/HighlightStyle.kt +19 -0
- package/android/src/main/java/com/renderrichtext/styles/ImageStyle.kt +29 -0
- package/android/src/main/java/com/renderrichtext/styles/InlineImageStyle.kt +17 -0
- package/android/src/main/java/com/renderrichtext/styles/InlineMathStyle.kt +17 -0
- package/android/src/main/java/com/renderrichtext/styles/LinkPillContent.kt +36 -0
- package/android/src/main/java/com/renderrichtext/styles/LinkPillStyle.kt +44 -0
- package/android/src/main/java/com/renderrichtext/styles/LinkStyle.kt +23 -0
- package/android/src/main/java/com/renderrichtext/styles/LinkVariantEntry.kt +34 -0
- package/android/src/main/java/com/renderrichtext/styles/ListStyle.kt +65 -0
- package/android/src/main/java/com/renderrichtext/styles/MathStyle.kt +29 -0
- package/android/src/main/java/com/renderrichtext/styles/MentionStyle.kt +19 -0
- package/android/src/main/java/com/renderrichtext/styles/ParagraphStyle.kt +33 -0
- package/android/src/main/java/com/renderrichtext/styles/SpoilerStyle.kt +27 -0
- package/android/src/main/java/com/renderrichtext/styles/StrikethroughStyle.kt +17 -0
- package/android/src/main/java/com/renderrichtext/styles/StrongStyle.kt +21 -0
- package/android/src/main/java/com/renderrichtext/styles/StyleConfig.kt +411 -0
- package/android/src/main/java/com/renderrichtext/styles/StyleParser.kt +92 -0
- package/android/src/main/java/com/renderrichtext/styles/SubscriptStyle.kt +16 -0
- package/android/src/main/java/com/renderrichtext/styles/SuperscriptStyle.kt +16 -0
- package/android/src/main/java/com/renderrichtext/styles/TableStyle.kt +75 -0
- package/android/src/main/java/com/renderrichtext/styles/TaskListStyle.kt +29 -0
- package/android/src/main/java/com/renderrichtext/styles/TextAlignment.kt +32 -0
- package/android/src/main/java/com/renderrichtext/styles/ThematicBreakStyle.kt +23 -0
- package/android/src/main/java/com/renderrichtext/styles/UnderlineStyle.kt +17 -0
- package/android/src/main/java/com/renderrichtext/styles/VideoStyle.kt +31 -0
- package/android/src/main/java/com/renderrichtext/utils/common/BorderStyleUtils.kt +86 -0
- package/android/src/main/java/com/renderrichtext/utils/common/BreakStrategyUtils.kt +32 -0
- package/android/src/main/java/com/renderrichtext/utils/common/CodeBlockHighlighter.kt +36 -0
- package/android/src/main/java/com/renderrichtext/utils/common/CodeBlockNode.kt +42 -0
- package/android/src/main/java/com/renderrichtext/utils/common/EllipsizeUtils.kt +27 -0
- package/android/src/main/java/com/renderrichtext/utils/common/EnrichedTiptapAncestorUtils.kt +10 -0
- package/android/src/main/java/com/renderrichtext/utils/common/FeatureFlags.kt +9 -0
- package/android/src/main/java/com/renderrichtext/utils/common/LinkRecognitionProps.kt +31 -0
- package/android/src/main/java/com/renderrichtext/utils/common/LinkRegexConfig.kt +56 -0
- package/android/src/main/java/com/renderrichtext/utils/common/MotionPreferences.kt +18 -0
- package/android/src/main/java/com/renderrichtext/utils/common/ReadableMapExtensions.kt +28 -0
- package/android/src/main/java/com/renderrichtext/utils/common/TiptapViewManagerUtils.kt +242 -0
- package/android/src/main/java/com/renderrichtext/utils/common/layout/RTLUtils.kt +6 -0
- package/android/src/main/java/com/renderrichtext/utils/common/serialization/TiptapASTSerializer.kt +368 -0
- package/android/src/main/java/com/renderrichtext/utils/text/ImageCache.kt +88 -0
- package/android/src/main/java/com/renderrichtext/utils/text/ImageDownloader.kt +203 -0
- package/android/src/main/java/com/renderrichtext/utils/text/LocalImageLoader.kt +167 -0
- package/android/src/main/java/com/renderrichtext/utils/text/TailFadeInAnimator.kt +84 -0
- package/android/src/main/java/com/renderrichtext/utils/text/conversion/HTMLGenerator.kt +1105 -0
- package/android/src/main/java/com/renderrichtext/utils/text/conversion/TiptapExtractor.kt +423 -0
- package/android/src/main/java/com/renderrichtext/utils/text/extensions/ParagraphUtils.kt +9 -0
- package/android/src/main/java/com/renderrichtext/utils/text/extensions/SpannableExtensions.kt +9 -0
- package/android/src/main/java/com/renderrichtext/utils/text/extensions/TextPaintExtensions.kt +76 -0
- package/android/src/main/java/com/renderrichtext/utils/text/interaction/CheckboxTouchHelper.kt +61 -0
- package/android/src/main/java/com/renderrichtext/utils/text/interaction/TaskListTapUtils.kt +286 -0
- package/android/src/main/java/com/renderrichtext/utils/text/span/ApplyLineHeight.kt +39 -0
- package/android/src/main/java/com/renderrichtext/utils/text/span/BlockSpacing.kt +142 -0
- package/android/src/main/java/com/renderrichtext/utils/text/span/SpanFlags.kt +43 -0
- package/android/src/main/java/com/renderrichtext/utils/text/span/WidthAwareSpans.kt +30 -0
- package/android/src/main/java/com/renderrichtext/utils/text/view/CodeBlockPressHost.kt +15 -0
- package/android/src/main/java/com/renderrichtext/utils/text/view/ImagePressHost.kt +19 -0
- package/android/src/main/java/com/renderrichtext/utils/text/view/LinkEvents.kt +88 -0
- package/android/src/main/java/com/renderrichtext/utils/text/view/LinkLongPressMovementMethod.kt +449 -0
- package/android/src/main/java/com/renderrichtext/utils/text/view/SelectionActionMode.kt +235 -0
- package/android/src/main/java/com/renderrichtext/utils/text/view/TextSelectionColors.kt +48 -0
- package/android/src/main/java/com/renderrichtext/utils/text/view/TextViewSetup.kt +119 -0
- package/android/src/main/java/com/renderrichtext/views/ContextMenuPopup.kt +217 -0
- package/android/src/main/java/com/renderrichtext/views/CopyGlyph.kt +101 -0
- package/android/src/main/java/com/renderrichtext/views/WrapGlyph.kt +40 -0
- package/android/src/main/jni/CMakeLists.txt +52 -0
- package/android/src/main/jni/react/renderer/components/RichTextSpec/ComponentDescriptors.h +30 -0
- package/android/src/main/jni/react/renderer/components/RichTextSpec/TiptapTextComponentDescriptor.h +29 -0
- package/android/src/main/jni/react/renderer/components/RichTextSpec/TiptapTextMeasurementManager.cpp +45 -0
- package/android/src/main/jni/react/renderer/components/RichTextSpec/TiptapTextMeasurementManager.h +21 -0
- package/android/src/main/jni/react/renderer/components/RichTextSpec/TiptapTextShadowNode.cpp +38 -0
- package/android/src/main/jni/react/renderer/components/RichTextSpec/TiptapTextShadowNode.h +53 -0
- package/android/src/main/jni/react/renderer/components/RichTextSpec/TiptapTextState.cpp +9 -0
- package/android/src/main/jni/react/renderer/components/RichTextSpec/TiptapTextState.h +24 -0
- package/android/src/main/jni/react/renderer/components/RichTextSpec/conversions.h +40 -0
- package/cpp/parser/TiptapASTNode.hpp +68 -0
- package/cpp/parser/TiptapParser.cpp +233 -0
- package/cpp/parser/TiptapParser.hpp +13 -0
- package/cpp/vendor/nlohmann/json.hpp +24765 -0
- package/ios/EnrichedTiptapText.h +27 -0
- package/ios/EnrichedTiptapText.mm +1222 -0
- package/ios/attachments/ENRMImageAttachment.h +51 -0
- package/ios/attachments/ENRMImageAttachment.m +398 -0
- package/ios/attachments/ENRMLinkPillAttachment.h +47 -0
- package/ios/attachments/ENRMLinkPillAttachment.m +324 -0
- package/ios/attachments/ENRMLinkPillIconCache.h +28 -0
- package/ios/attachments/ENRMLinkPillIconCache.m +181 -0
- package/ios/attachments/ENRMLinkPillText.h +27 -0
- package/ios/attachments/ENRMLinkPillText.m +118 -0
- package/ios/attachments/ENRMMathInlineAttachment.h +7 -0
- package/ios/attachments/ENRMMathInlineAttachment.m +4 -0
- package/ios/attachments/ThematicBreakAttachment.h +15 -0
- package/ios/attachments/ThematicBreakAttachment.m +33 -0
- package/ios/internals/ENRMViewFreeMeasurement.h +208 -0
- package/ios/internals/EnrichedTiptapTextComponentDescriptor.h +19 -0
- package/ios/internals/EnrichedTiptapTextShadowNode.h +43 -0
- package/ios/internals/EnrichedTiptapTextShadowNode.mm +69 -0
- package/ios/internals/EnrichedTiptapTextState.h +24 -0
- package/ios/internals/MeasurementCache.h +308 -0
- package/ios/internals/ShadowMeasurementUtils.h +145 -0
- package/ios/parser/ENRMTextLinkAttributes.h +7 -0
- package/ios/parser/ENRMTiptapParser.h +33 -0
- package/ios/parser/ENRMTiptapParser.mm +73 -0
- package/ios/parser/TiptapASTNode.h +57 -0
- package/ios/parser/TiptapASTNode.m +52 -0
- package/ios/parser/TiptapParserBridge.mm +179 -0
- package/ios/renderer/AttributedRenderer.h +23 -0
- package/ios/renderer/AttributedRenderer.m +229 -0
- package/ios/renderer/BaseRenderer.h +33 -0
- package/ios/renderer/BaseRenderer.m +46 -0
- package/ios/renderer/BaselineShiftTextAttributes.h +10 -0
- package/ios/renderer/BaselineShiftTextAttributes.m +26 -0
- package/ios/renderer/BlankLineRenderer.h +4 -0
- package/ios/renderer/BlankLineRenderer.m +51 -0
- package/ios/renderer/BlockquoteRenderer.h +6 -0
- package/ios/renderer/BlockquoteRenderer.m +258 -0
- package/ios/renderer/CodeBlockRenderer.h +9 -0
- package/ios/renderer/CodeBlockRenderer.m +99 -0
- package/ios/renderer/CodeRenderer.h +9 -0
- package/ios/renderer/CodeRenderer.m +69 -0
- package/ios/renderer/ENRMBlockquoteTextRenderer.h +25 -0
- package/ios/renderer/ENRMBlockquoteTextRenderer.m +48 -0
- package/ios/renderer/EmphasisRenderer.h +5 -0
- package/ios/renderer/EmphasisRenderer.m +100 -0
- package/ios/renderer/FactoidRenderer.h +9 -0
- package/ios/renderer/FactoidRenderer.m +130 -0
- package/ios/renderer/HeadingRenderer.h +6 -0
- package/ios/renderer/HeadingRenderer.m +103 -0
- package/ios/renderer/HighlightRenderer.h +7 -0
- package/ios/renderer/HighlightRenderer.m +33 -0
- package/ios/renderer/LinkRenderer.h +6 -0
- package/ios/renderer/LinkRenderer.m +158 -0
- package/ios/renderer/ListItemRenderer.h +24 -0
- package/ios/renderer/ListItemRenderer.m +283 -0
- package/ios/renderer/ListRenderer.h +13 -0
- package/ios/renderer/ListRenderer.m +126 -0
- package/ios/renderer/MentionRenderer.h +9 -0
- package/ios/renderer/MentionRenderer.m +96 -0
- package/ios/renderer/NodeRenderer.h +8 -0
- package/ios/renderer/ParagraphRenderer.h +6 -0
- package/ios/renderer/ParagraphRenderer.m +85 -0
- package/ios/renderer/RenderContext.h +145 -0
- package/ios/renderer/RenderContext.m +403 -0
- package/ios/renderer/RendererFactory.h +12 -0
- package/ios/renderer/RendererFactory.m +158 -0
- package/ios/renderer/StrikethroughRenderer.h +5 -0
- package/ios/renderer/StrikethroughRenderer.m +30 -0
- package/ios/renderer/StrongRenderer.h +5 -0
- package/ios/renderer/StrongRenderer.m +88 -0
- package/ios/renderer/TextRenderer.h +6 -0
- package/ios/renderer/TextRenderer.m +18 -0
- package/ios/renderer/ThematicBreakRenderer.h +4 -0
- package/ios/renderer/ThematicBreakRenderer.m +42 -0
- package/ios/renderer/UnderlineRenderer.h +4 -0
- package/ios/renderer/UnderlineRenderer.m +41 -0
- package/ios/styles/ENRMFontSlot.h +12 -0
- package/ios/styles/ENRMFontSlot.m +24 -0
- package/ios/styles/StyleConfig.h +488 -0
- package/ios/styles/StyleConfig.mm +2820 -0
- package/ios/utils/AccessibilityInfo.h +35 -0
- package/ios/utils/AccessibilityInfo.m +24 -0
- package/ios/utils/BlockquoteBorder.h +26 -0
- package/ios/utils/BlockquoteBorder.m +294 -0
- package/ios/utils/CodeBackground.h +19 -0
- package/ios/utils/CodeBackground.m +197 -0
- package/ios/utils/CodeBlockBackground.h +17 -0
- package/ios/utils/CodeBlockBackground.m +103 -0
- package/ios/utils/ContextMenuUtils.h +76 -0
- package/ios/utils/ContextMenuUtils.mm +75 -0
- package/ios/utils/ENRMAccessibilityLabels.h +40 -0
- package/ios/utils/ENRMAccessibilityLabels.m +5 -0
- package/ios/utils/ENRMAsyncRenderCoordinator.h +24 -0
- package/ios/utils/ENRMAsyncRenderCoordinator.m +37 -0
- package/ios/utils/ENRMAtomicSize.h +65 -0
- package/ios/utils/ENRMCodeBlockContent.h +37 -0
- package/ios/utils/ENRMCodeBlockContent.mm +89 -0
- package/ios/utils/ENRMFeatureFlags.h +25 -0
- package/ios/utils/ENRMImageDownloader.h +30 -0
- package/ios/utils/ENRMImageDownloader.m +168 -0
- package/ios/utils/ENRMLatexErrorCoordinator.h +27 -0
- package/ios/utils/ENRMLatexErrorCoordinator.mm +75 -0
- package/ios/utils/ENRMLatexErrorReporting.h +13 -0
- package/ios/utils/ENRMLinkContextMenus.h +93 -0
- package/ios/utils/ENRMLinkContextMenus.m +178 -0
- package/ios/utils/ENRMLinkRegexConfig.h +30 -0
- package/ios/utils/ENRMLinkRegexConfig.mm +104 -0
- package/ios/utils/ENRMLinkRegexProps.h +23 -0
- package/ios/utils/ENRMLocalImageLoader.h +35 -0
- package/ios/utils/ENRMLocalImageLoader.m +111 -0
- package/ios/utils/ENRMMenuAction.h +27 -0
- package/ios/utils/ENRMMenuAction.m +33 -0
- package/ios/utils/ENRMSpoilerOverlayManager.h +15 -0
- package/ios/utils/ENRMSpoilerOverlayManager.m +19 -0
- package/ios/utils/ENRMSpoilerTapUtils.h +6 -0
- package/ios/utils/ENRMSpoilerTapUtils.m +11 -0
- package/ios/utils/ENRMTailFadeInAnimator.h +16 -0
- package/ios/utils/ENRMTailFadeInAnimator.m +161 -0
- package/ios/utils/ENRMTextHitTest.h +23 -0
- package/ios/utils/ENRMTextHitTest.m +20 -0
- package/ios/utils/ENRMTextInteractionUtils.h +20 -0
- package/ios/utils/ENRMTextInteractionUtils.m +15 -0
- package/ios/utils/ENRMTextRenderer.h +38 -0
- package/ios/utils/ENRMTextRenderer.m +54 -0
- package/ios/utils/ENRMTextViewSetup.h +132 -0
- package/ios/utils/ENRMUIKit.h +429 -0
- package/ios/utils/EditMenuUtils.h +105 -0
- package/ios/utils/EditMenuUtils.m +143 -0
- package/ios/utils/FactoidBackground.h +20 -0
- package/ios/utils/FactoidBackground.m +161 -0
- package/ios/utils/FontScaleObserver.h +10 -0
- package/ios/utils/FontScaleObserver.m +55 -0
- package/ios/utils/FontUtils.h +31 -0
- package/ios/utils/FontUtils.m +63 -0
- package/ios/utils/HTMLGenerator.h +25 -0
- package/ios/utils/HTMLGenerator.m +1041 -0
- package/ios/utils/HeightUpdateUtils.h +25 -0
- package/ios/utils/ImageRequestHeaderUtils.h +35 -0
- package/ios/utils/LastElementUtils.h +97 -0
- package/ios/utils/LinkContextMenuUtils.h +55 -0
- package/ios/utils/LinkPillContentUtils.h +46 -0
- package/ios/utils/LinkTapUtils.h +56 -0
- package/ios/utils/LinkTapUtils.m +139 -0
- package/ios/utils/ListMarkerDrawer.h +15 -0
- package/ios/utils/ListMarkerDrawer.m +239 -0
- package/ios/utils/MentionBackground.h +26 -0
- package/ios/utils/MentionBackground.m +86 -0
- package/ios/utils/ParagraphStyleUtils.h +87 -0
- package/ios/utils/ParagraphStyleUtils.m +484 -0
- package/ios/utils/PasteboardUtils.h +48 -0
- package/ios/utils/PasteboardUtils.m +166 -0
- package/ios/utils/RTFExportUtils.h +24 -0
- package/ios/utils/RTFExportUtils.m +299 -0
- package/ios/utils/RuntimeKeys.h +44 -0
- package/ios/utils/RuntimeKeys.m +13 -0
- package/ios/utils/SelectionColorUtils.h +14 -0
- package/ios/utils/StylePropsUtils.h +1340 -0
- package/ios/utils/TaskListTapUtils.h +6 -0
- package/ios/utils/TaskListTapUtils.m +14 -0
- package/ios/utils/TextViewLayoutManager.h +14 -0
- package/ios/utils/TextViewLayoutManager.mm +198 -0
- package/ios/utils/TiptapAccessibilityElementBuilder.h +43 -0
- package/ios/utils/TiptapAccessibilityElementBuilder.m +432 -0
- package/ios/utils/TiptapExtractor.h +17 -0
- package/ios/utils/TiptapExtractor.m +367 -0
- package/ios/views/ENRMTiptapTextView.h +25 -0
- package/ios/views/ENRMTiptapTextView.m +247 -0
- package/package.json +70 -6
- package/react-native.config.js +10 -0
- package/src/EnrichedTiptapTextNativeComponent.ts +739 -0
- package/src/RichText.tsx +164 -0
- package/src/admonitionDefaults.ts +58 -0
- package/src/darkModeTextStyle.ts +99 -0
- package/src/headingDefaults.ts +21 -0
- package/src/index.tsx +4 -0
- package/src/linkVariantUtils.ts +120 -0
- package/src/normalizeTiptapStyle.ts +397 -0
- package/src/rn-globals.d.ts +1 -0
- package/src/styleUtils.ts +107 -0
- package/src/types/TiptapStyle.ts +532 -0
- package/src/types/TiptapStyleInternal.ts +299 -0
- package/src/types/linkPill.ts +9 -0
- package/src/utils/isDev.ts +4 -0
|
@@ -0,0 +1,76 @@
|
|
|
1
|
+
package com.renderrichtext.spans
|
|
2
|
+
|
|
3
|
+
import android.graphics.Paint
|
|
4
|
+
import android.text.style.LineHeightSpan
|
|
5
|
+
|
|
6
|
+
/**
|
|
7
|
+
* Adds bottom margin to a block element (paragraphs/headings) using LineHeightSpan.
|
|
8
|
+
*
|
|
9
|
+
* For spacer lines (single newline), sets the line height to exactly marginBottom.
|
|
10
|
+
* For regular lines, adds marginBottom only at paragraph boundaries to preserve lineHeight.
|
|
11
|
+
*
|
|
12
|
+
* @param marginBottom The margin in pixels to add below the block (0 = no margin)
|
|
13
|
+
*/
|
|
14
|
+
class MarginBottomSpan(
|
|
15
|
+
val marginBottom: Float,
|
|
16
|
+
) : LineHeightSpan {
|
|
17
|
+
override fun chooseHeight(
|
|
18
|
+
text: CharSequence,
|
|
19
|
+
start: Int,
|
|
20
|
+
end: Int,
|
|
21
|
+
spanstartv: Int,
|
|
22
|
+
lineHeight: Int,
|
|
23
|
+
fm: Paint.FontMetricsInt,
|
|
24
|
+
) {
|
|
25
|
+
// Only process lines that end with a newline
|
|
26
|
+
if (end <= start || text[end - 1] != '\n') {
|
|
27
|
+
return
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
val marginPixels = marginBottom.toInt()
|
|
31
|
+
|
|
32
|
+
// Handle spacer lines (single newline character)
|
|
33
|
+
if (end - start == 1 && text[start] == '\n') {
|
|
34
|
+
if (hasContentAfter(text, end)) {
|
|
35
|
+
// Set line height to exactly marginBottom for spacer lines
|
|
36
|
+
fm.top = 0
|
|
37
|
+
fm.ascent = 0
|
|
38
|
+
fm.descent = marginPixels
|
|
39
|
+
fm.bottom = marginPixels
|
|
40
|
+
} else {
|
|
41
|
+
// No content after - collapse the spacer line to zero height
|
|
42
|
+
fm.top = 0
|
|
43
|
+
fm.ascent = 0
|
|
44
|
+
fm.descent = 0
|
|
45
|
+
fm.bottom = 0
|
|
46
|
+
}
|
|
47
|
+
return
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
// For regular lines, add spacing only if there's content after
|
|
51
|
+
if (hasContentAfter(text, end)) {
|
|
52
|
+
fm.descent += marginPixels
|
|
53
|
+
fm.bottom += marginPixels
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
/**
|
|
58
|
+
* Checks if there's non-newline content after the given position.
|
|
59
|
+
* Used to determine if spacing should be applied (between items) or skipped (after last item).
|
|
60
|
+
*/
|
|
61
|
+
private fun hasContentAfter(
|
|
62
|
+
text: CharSequence,
|
|
63
|
+
pos: Int,
|
|
64
|
+
): Boolean {
|
|
65
|
+
if (pos >= text.length) return false
|
|
66
|
+
|
|
67
|
+
// If the next character is a newline, check the character after that
|
|
68
|
+
if (text[pos] == '\n') {
|
|
69
|
+
val nextPos = pos + 1
|
|
70
|
+
if (nextPos >= text.length) return false
|
|
71
|
+
return text[nextPos] != '\n' // Non-newline = content exists
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
return true // Non-newline content immediately after
|
|
75
|
+
}
|
|
76
|
+
}
|
|
@@ -0,0 +1,132 @@
|
|
|
1
|
+
package com.renderrichtext.spans
|
|
2
|
+
|
|
3
|
+
import android.graphics.Canvas
|
|
4
|
+
import android.graphics.Color
|
|
5
|
+
import android.graphics.Paint
|
|
6
|
+
import android.graphics.RectF
|
|
7
|
+
import android.graphics.Typeface
|
|
8
|
+
import android.os.Build
|
|
9
|
+
import android.text.style.ReplacementSpan
|
|
10
|
+
import kotlin.math.ceil
|
|
11
|
+
|
|
12
|
+
/**
|
|
13
|
+
* One unbreakable chip for a mention. Material chips stay on a single line, so the
|
|
14
|
+
* whole `@name` is one replacement run: the line breaker wraps it as a unit, and the
|
|
15
|
+
* horizontal padding is part of that width rather than a separate gap that can be
|
|
16
|
+
* left behind on the previous line.
|
|
17
|
+
*
|
|
18
|
+
* Each line fragment of an iOS mention is its own rounded rect. Android does not
|
|
19
|
+
* split the chip, which is how inline people-chips behave in Material text.
|
|
20
|
+
*/
|
|
21
|
+
class MentionChipSpan(
|
|
22
|
+
private val backgroundColor: Int,
|
|
23
|
+
private val textColor: Int,
|
|
24
|
+
private val paddingX: Float,
|
|
25
|
+
private val paddingY: Float,
|
|
26
|
+
) : ReplacementSpan() {
|
|
27
|
+
/** True while a finger is down. The movement method sets this and re-sets the span so the new fill is recorded. */
|
|
28
|
+
var pressed: Boolean = false
|
|
29
|
+
|
|
30
|
+
private val fillPaint = Paint(Paint.ANTI_ALIAS_FLAG).apply { style = Paint.Style.FILL }
|
|
31
|
+
private val rect = RectF()
|
|
32
|
+
private var cachedSource: Typeface? = null
|
|
33
|
+
private var cachedMedium: Typeface? = null
|
|
34
|
+
|
|
35
|
+
override fun getSize(
|
|
36
|
+
paint: Paint,
|
|
37
|
+
text: CharSequence,
|
|
38
|
+
start: Int,
|
|
39
|
+
end: Int,
|
|
40
|
+
fm: Paint.FontMetricsInt?,
|
|
41
|
+
): Int {
|
|
42
|
+
var width = 0
|
|
43
|
+
paint.usingMedium {
|
|
44
|
+
if (fm != null) {
|
|
45
|
+
paint.getFontMetricsInt(fm)
|
|
46
|
+
val extra = ceil(paddingY).toInt()
|
|
47
|
+
fm.ascent -= extra
|
|
48
|
+
fm.top -= extra
|
|
49
|
+
fm.descent += extra
|
|
50
|
+
fm.bottom += extra
|
|
51
|
+
}
|
|
52
|
+
width = ceil(paint.measureText(text, start, end) + paddingX * 2f).toInt()
|
|
53
|
+
}
|
|
54
|
+
return width
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
override fun draw(
|
|
58
|
+
canvas: Canvas,
|
|
59
|
+
text: CharSequence,
|
|
60
|
+
start: Int,
|
|
61
|
+
end: Int,
|
|
62
|
+
x: Float,
|
|
63
|
+
top: Int,
|
|
64
|
+
y: Int,
|
|
65
|
+
bottom: Int,
|
|
66
|
+
paint: Paint,
|
|
67
|
+
) {
|
|
68
|
+
paint.usingMedium {
|
|
69
|
+
val textWidth = paint.measureText(text, start, end)
|
|
70
|
+
val metrics = paint.fontMetrics
|
|
71
|
+
rect.set(
|
|
72
|
+
x,
|
|
73
|
+
y + metrics.ascent - paddingY,
|
|
74
|
+
x + textWidth + paddingX * 2f,
|
|
75
|
+
y + metrics.descent + paddingY,
|
|
76
|
+
)
|
|
77
|
+
val radius = 10f
|
|
78
|
+
var fill = backgroundColor
|
|
79
|
+
if (pressed) fill = darken(fill)
|
|
80
|
+
if (Color.alpha(fill) > 0) {
|
|
81
|
+
fillPaint.color = fill
|
|
82
|
+
canvas.drawRoundRect(rect, radius, radius, fillPaint)
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
val previousColor = paint.color
|
|
86
|
+
paint.color = textColor
|
|
87
|
+
canvas.drawText(text, start, end, x + paddingX, y.toFloat(), paint)
|
|
88
|
+
paint.color = previousColor
|
|
89
|
+
}
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
private fun darken(color: Int): Int =
|
|
93
|
+
Color.argb(
|
|
94
|
+
Color.alpha(color),
|
|
95
|
+
(Color.red(color) * PRESSED_DARKEN).toInt(),
|
|
96
|
+
(Color.green(color) * PRESSED_DARKEN).toInt(),
|
|
97
|
+
(Color.blue(color) * PRESSED_DARKEN).toInt(),
|
|
98
|
+
)
|
|
99
|
+
|
|
100
|
+
/**
|
|
101
|
+
* Medium is the Android weight for a name in body text. API 28 keeps the surrounding
|
|
102
|
+
* family. Older releases have no weight axis, so the face becomes sans-serif-medium.
|
|
103
|
+
*/
|
|
104
|
+
private fun mediumTypeface(base: Typeface?): Typeface {
|
|
105
|
+
if (cachedMedium != null && cachedSource === base) return cachedMedium!!
|
|
106
|
+
val source = base ?: Typeface.SANS_SERIF
|
|
107
|
+
val italic = source.style and Typeface.ITALIC != 0
|
|
108
|
+
val created =
|
|
109
|
+
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.P) {
|
|
110
|
+
Typeface.create(source, 500, italic)
|
|
111
|
+
} else {
|
|
112
|
+
Typeface.create("sans-serif-medium", if (italic) Typeface.ITALIC else Typeface.NORMAL)
|
|
113
|
+
}
|
|
114
|
+
cachedSource = base
|
|
115
|
+
cachedMedium = created
|
|
116
|
+
return created
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
private inline fun Paint.usingMedium(block: () -> Unit) {
|
|
120
|
+
val original = typeface
|
|
121
|
+
typeface = mediumTypeface(original)
|
|
122
|
+
try {
|
|
123
|
+
block()
|
|
124
|
+
} finally {
|
|
125
|
+
typeface = original
|
|
126
|
+
}
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
companion object {
|
|
130
|
+
private const val PRESSED_DARKEN = 0.82f
|
|
131
|
+
}
|
|
132
|
+
}
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
package com.renderrichtext.spans
|
|
2
|
+
|
|
3
|
+
import android.text.TextPaint
|
|
4
|
+
import android.text.style.ClickableSpan
|
|
5
|
+
import android.view.View
|
|
6
|
+
import com.renderrichtext.EnrichedTiptapText
|
|
7
|
+
|
|
8
|
+
/**
|
|
9
|
+
* Click and long-press target for a mention. The chip span draws the glyphs, so this
|
|
10
|
+
* only supplies the text color and the gestures. No underline: a mention is a chip,
|
|
11
|
+
* not a link.
|
|
12
|
+
*/
|
|
13
|
+
class MentionSpan(
|
|
14
|
+
val mentionId: String,
|
|
15
|
+
val label: String,
|
|
16
|
+
private val textColor: Int,
|
|
17
|
+
private val onMentionPress: ((String, String) -> Unit)?,
|
|
18
|
+
private val onMentionLongPress: ((String, String) -> Unit)?,
|
|
19
|
+
) : ClickableSpan() {
|
|
20
|
+
/** True while a finger is down on this mention. The chip's own flag is what it draws. */
|
|
21
|
+
var pressed: Boolean = false
|
|
22
|
+
|
|
23
|
+
@Volatile
|
|
24
|
+
private var longPressTriggered = false
|
|
25
|
+
|
|
26
|
+
override fun onClick(widget: View) {
|
|
27
|
+
if (longPressTriggered) {
|
|
28
|
+
longPressTriggered = false
|
|
29
|
+
return
|
|
30
|
+
}
|
|
31
|
+
onMentionPress?.invoke(mentionId, label)
|
|
32
|
+
?: (widget as? EnrichedTiptapText)?.emitOnMentionPress(mentionId, label)
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
fun onLongClick(widget: View): Boolean {
|
|
36
|
+
longPressTriggered = true
|
|
37
|
+
onMentionLongPress?.invoke(mentionId, label)
|
|
38
|
+
?: (widget as? EnrichedTiptapText)?.emitOnMentionLongPress(mentionId, label)
|
|
39
|
+
return true
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
override fun updateDrawState(textPaint: TextPaint) {
|
|
43
|
+
textPaint.color = textColor
|
|
44
|
+
textPaint.isUnderlineText = false
|
|
45
|
+
}
|
|
46
|
+
}
|
|
@@ -0,0 +1,127 @@
|
|
|
1
|
+
package com.renderrichtext.spans
|
|
2
|
+
|
|
3
|
+
import android.content.Context
|
|
4
|
+
import android.graphics.Canvas
|
|
5
|
+
import android.graphics.Paint
|
|
6
|
+
import android.graphics.Typeface
|
|
7
|
+
import android.text.Layout
|
|
8
|
+
import android.text.TextPaint
|
|
9
|
+
import com.facebook.react.common.ReactConstants
|
|
10
|
+
import com.facebook.react.views.text.ReactTypefaceUtils.applyStyles
|
|
11
|
+
import com.facebook.react.views.text.ReactTypefaceUtils.parseFontWeight
|
|
12
|
+
import com.renderrichtext.renderer.BlockStyle
|
|
13
|
+
import com.renderrichtext.renderer.SpanStyleCache
|
|
14
|
+
import com.renderrichtext.styles.ListStyle
|
|
15
|
+
import kotlin.math.ceil
|
|
16
|
+
|
|
17
|
+
class OrderedListSpan(
|
|
18
|
+
private val listStyle: ListStyle,
|
|
19
|
+
depth: Int,
|
|
20
|
+
context: Context,
|
|
21
|
+
styleCache: SpanStyleCache,
|
|
22
|
+
drawsMarker: Boolean = true,
|
|
23
|
+
override val markerExtraWidth: Float = 0f,
|
|
24
|
+
ancestorMarkerOffset: Float = 0f,
|
|
25
|
+
parentMarkerWidth: Float? = null,
|
|
26
|
+
) : BaseListSpan(
|
|
27
|
+
depth = depth,
|
|
28
|
+
context = context,
|
|
29
|
+
styleCache = styleCache,
|
|
30
|
+
blockStyle =
|
|
31
|
+
BlockStyle(
|
|
32
|
+
fontSize = listStyle.fontSize,
|
|
33
|
+
fontFamily = listStyle.fontFamily,
|
|
34
|
+
fontWeight = listStyle.fontWeight,
|
|
35
|
+
color = listStyle.color,
|
|
36
|
+
),
|
|
37
|
+
marginLeft = listStyle.marginLeft,
|
|
38
|
+
gapWidth = listStyle.gapWidth,
|
|
39
|
+
drawsMarker = drawsMarker,
|
|
40
|
+
ancestorMarkerOffset = ancestorMarkerOffset,
|
|
41
|
+
parentMarkerWidth = parentMarkerWidth,
|
|
42
|
+
) {
|
|
43
|
+
companion object {
|
|
44
|
+
private val sharedMarkerPaint = TextPaint().apply { isAntiAlias = true }
|
|
45
|
+
|
|
46
|
+
/** Column every bullet and numbered list reserves, wide enough for `99.`. */
|
|
47
|
+
fun defaultMarkerColumnWidth(
|
|
48
|
+
listStyle: ListStyle,
|
|
49
|
+
context: Context,
|
|
50
|
+
): Float {
|
|
51
|
+
val paint = markerPaint(listStyle, markerTypeface(listStyle, context))
|
|
52
|
+
return listStyle.effectiveMarkerWidth(paint.measureText("99."))
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
/**
|
|
56
|
+
* How far the `99.` column every ordered list reserves must grow to fit each of [numbers].
|
|
57
|
+
* Whole pixels, so the Int leading margins and the float marker positions agree at every depth.
|
|
58
|
+
*/
|
|
59
|
+
fun measureExtraWidth(
|
|
60
|
+
listStyle: ListStyle,
|
|
61
|
+
context: Context,
|
|
62
|
+
numbers: Iterable<Int>,
|
|
63
|
+
): Float {
|
|
64
|
+
val paint = markerPaint(listStyle, markerTypeface(listStyle, context))
|
|
65
|
+
val default = paint.measureText("99.")
|
|
66
|
+
val widest = numbers.fold(default) { width, number -> maxOf(width, paint.measureText("$number.")) }
|
|
67
|
+
return ceil(listStyle.effectiveMarkerWidth(widest) - listStyle.effectiveMarkerWidth(default))
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
private fun markerTypeface(
|
|
71
|
+
listStyle: ListStyle,
|
|
72
|
+
context: Context,
|
|
73
|
+
): Typeface =
|
|
74
|
+
applyStyles(
|
|
75
|
+
null,
|
|
76
|
+
ReactConstants.UNSET,
|
|
77
|
+
parseFontWeight(listStyle.markerFontWeight),
|
|
78
|
+
listStyle.fontFamily.takeIf { it.isNotEmpty() },
|
|
79
|
+
context.assets,
|
|
80
|
+
)
|
|
81
|
+
|
|
82
|
+
private fun markerPaint(
|
|
83
|
+
listStyle: ListStyle,
|
|
84
|
+
typeface: Typeface,
|
|
85
|
+
): TextPaint =
|
|
86
|
+
sharedMarkerPaint.apply {
|
|
87
|
+
textSize = listStyle.fontSize
|
|
88
|
+
color = listStyle.markerColor
|
|
89
|
+
this.typeface = typeface
|
|
90
|
+
}
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
private val markerTypeface = markerTypeface(listStyle, context)
|
|
94
|
+
private val defaultMarkerWidth = defaultMarkerColumnWidth(listStyle, context)
|
|
95
|
+
|
|
96
|
+
override fun getMarkerWidth(): Float = defaultMarkerWidth + markerExtraWidth
|
|
97
|
+
|
|
98
|
+
override val baselineMarkerWidth: Float get() = defaultMarkerWidth
|
|
99
|
+
|
|
100
|
+
var itemNumber: Int = 1
|
|
101
|
+
private set
|
|
102
|
+
|
|
103
|
+
override fun drawMarker(
|
|
104
|
+
canvas: Canvas,
|
|
105
|
+
paint: Paint,
|
|
106
|
+
x: Int,
|
|
107
|
+
dir: Int,
|
|
108
|
+
top: Int,
|
|
109
|
+
baseline: Int,
|
|
110
|
+
bottom: Int,
|
|
111
|
+
layout: Layout?,
|
|
112
|
+
start: Int,
|
|
113
|
+
) {
|
|
114
|
+
val markerPaint = markerPaint(listStyle, markerTypeface)
|
|
115
|
+
val text = if (dir < 0) ".$itemNumber" else "$itemNumber."
|
|
116
|
+
val textWidth = markerPaint.measureText(text)
|
|
117
|
+
|
|
118
|
+
val markerRightEdge = x + (depth * marginLeft + ancestorMarkerOffset + getMarkerWidth()) * dir
|
|
119
|
+
val markerX = if (dir > 0) markerRightEdge - textWidth else markerRightEdge
|
|
120
|
+
|
|
121
|
+
canvas.drawText(text, markerX, baseline.toFloat(), markerPaint)
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
fun setItemNumber(number: Int) {
|
|
125
|
+
itemNumber = number
|
|
126
|
+
}
|
|
127
|
+
}
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
package com.renderrichtext.spans
|
|
2
|
+
|
|
3
|
+
import android.text.TextPaint
|
|
4
|
+
import android.text.style.MetricAffectingSpan
|
|
5
|
+
import com.renderrichtext.renderer.BlockStyle
|
|
6
|
+
import com.renderrichtext.renderer.SpanStyleCache
|
|
7
|
+
|
|
8
|
+
class SpoilerSpan(
|
|
9
|
+
val styleCache: SpanStyleCache,
|
|
10
|
+
val blockStyle: BlockStyle,
|
|
11
|
+
) : MetricAffectingSpan() {
|
|
12
|
+
var revealed = false
|
|
13
|
+
private set
|
|
14
|
+
var revealing = false
|
|
15
|
+
private set
|
|
16
|
+
|
|
17
|
+
fun markRevealing() {
|
|
18
|
+
revealing = true
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
fun markRevealed() {
|
|
22
|
+
revealed = true
|
|
23
|
+
revealing = false
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
override fun updateDrawState(tp: TextPaint) {
|
|
27
|
+
tp.textSize = blockStyle.fontSize
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
override fun updateMeasureState(tp: TextPaint) {
|
|
31
|
+
tp.textSize = blockStyle.fontSize
|
|
32
|
+
}
|
|
33
|
+
}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
package com.renderrichtext.spans
|
|
2
|
+
|
|
3
|
+
import android.text.TextPaint
|
|
4
|
+
import android.text.style.CharacterStyle
|
|
5
|
+
|
|
6
|
+
class StrikethroughSpan(
|
|
7
|
+
private val strikethroughColor: Int,
|
|
8
|
+
) : CharacterStyle() {
|
|
9
|
+
override fun updateDrawState(tp: TextPaint) {
|
|
10
|
+
tp.isStrikeThruText = true
|
|
11
|
+
}
|
|
12
|
+
}
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
package com.renderrichtext.spans
|
|
2
|
+
|
|
3
|
+
import android.graphics.Typeface
|
|
4
|
+
import android.text.TextPaint
|
|
5
|
+
import android.text.style.MetricAffectingSpan
|
|
6
|
+
import com.renderrichtext.renderer.BlockStyle
|
|
7
|
+
import com.renderrichtext.renderer.SpanStyleCache
|
|
8
|
+
import com.renderrichtext.utils.text.extensions.applyColorPreserving
|
|
9
|
+
|
|
10
|
+
class StrongSpan(
|
|
11
|
+
private val styleCache: SpanStyleCache,
|
|
12
|
+
private val blockStyle: BlockStyle,
|
|
13
|
+
) : MetricAffectingSpan() {
|
|
14
|
+
private val strongColor = styleCache.getStrongColorFor(blockStyle.color)
|
|
15
|
+
|
|
16
|
+
override fun updateDrawState(tp: TextPaint) {
|
|
17
|
+
applyStrongStyle(tp)
|
|
18
|
+
tp.applyColorPreserving(strongColor, *styleCache.colorsToPreserve)
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
override fun updateMeasureState(tp: TextPaint) {
|
|
22
|
+
applyStrongStyle(tp)
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
private fun applyStrongStyle(tp: TextPaint) {
|
|
26
|
+
tp.textSize = blockStyle.fontSize
|
|
27
|
+
|
|
28
|
+
val currentTypeface = tp.typeface ?: Typeface.DEFAULT
|
|
29
|
+
val isItalic = (currentTypeface.style) and Typeface.ITALIC != 0
|
|
30
|
+
val style = if (isItalic) Typeface.BOLD_ITALIC else Typeface.BOLD
|
|
31
|
+
tp.typeface =
|
|
32
|
+
if (styleCache.strongFontFamily.isNotEmpty()) {
|
|
33
|
+
val resolvedStyle = if (styleCache.strongFontWeight == "normal") Typeface.NORMAL else style
|
|
34
|
+
styleCache.getTypeface(styleCache.strongFontFamily, resolvedStyle)
|
|
35
|
+
} else {
|
|
36
|
+
Typeface.create(currentTypeface, style)
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
}
|
|
@@ -0,0 +1,143 @@
|
|
|
1
|
+
package com.renderrichtext.spans
|
|
2
|
+
|
|
3
|
+
import android.content.Context
|
|
4
|
+
import android.graphics.Canvas
|
|
5
|
+
import android.graphics.Paint
|
|
6
|
+
import android.graphics.Path
|
|
7
|
+
import android.graphics.RectF
|
|
8
|
+
import android.text.Layout
|
|
9
|
+
import com.renderrichtext.renderer.BlockStyle
|
|
10
|
+
import com.renderrichtext.renderer.SpanStyleCache
|
|
11
|
+
import com.renderrichtext.styles.ListStyle
|
|
12
|
+
import com.renderrichtext.styles.TaskListStyle
|
|
13
|
+
|
|
14
|
+
class TaskListSpan(
|
|
15
|
+
private val taskStyle: TaskListStyle,
|
|
16
|
+
private val listStyle: ListStyle,
|
|
17
|
+
depth: Int,
|
|
18
|
+
context: Context,
|
|
19
|
+
styleCache: SpanStyleCache,
|
|
20
|
+
val taskIndex: Int,
|
|
21
|
+
val isChecked: Boolean,
|
|
22
|
+
drawsMarker: Boolean = true,
|
|
23
|
+
ancestorMarkerOffset: Float = 0f,
|
|
24
|
+
override val markerExtraWidth: Float = 0f,
|
|
25
|
+
parentMarkerWidth: Float? = null,
|
|
26
|
+
) : BaseListSpan(
|
|
27
|
+
depth = depth,
|
|
28
|
+
context = context,
|
|
29
|
+
styleCache = styleCache,
|
|
30
|
+
blockStyle =
|
|
31
|
+
BlockStyle(
|
|
32
|
+
fontSize = listStyle.fontSize,
|
|
33
|
+
fontFamily = listStyle.fontFamily,
|
|
34
|
+
fontWeight = listStyle.fontWeight,
|
|
35
|
+
color = listStyle.color,
|
|
36
|
+
),
|
|
37
|
+
marginLeft = listStyle.marginLeft,
|
|
38
|
+
gapWidth = listStyle.gapWidth,
|
|
39
|
+
drawsMarker = drawsMarker,
|
|
40
|
+
ancestorMarkerOffset = ancestorMarkerOffset,
|
|
41
|
+
parentMarkerWidth = parentMarkerWidth,
|
|
42
|
+
) {
|
|
43
|
+
private val checkboxSize = taskStyle.checkboxSize
|
|
44
|
+
private val checkboxColumnWidth = listStyle.effectiveMarkerWidth(checkboxSize)
|
|
45
|
+
private val markerColumnWidth = checkboxColumnWidth + markerExtraWidth
|
|
46
|
+
private val cornerRadius = taskStyle.checkboxBorderRadius
|
|
47
|
+
private val rect = RectF()
|
|
48
|
+
private val checkPath = Path()
|
|
49
|
+
|
|
50
|
+
companion object {
|
|
51
|
+
private const val CAP_HEIGHT_RATIO = 0.72f
|
|
52
|
+
private const val HALF_DIVISOR = 2f
|
|
53
|
+
private const val CHECKMARK_MIN_STROKE_WIDTH = 1.5f
|
|
54
|
+
private const val CHECKMARK_STROKE_RATIO = 0.12f
|
|
55
|
+
private const val CHECKMARK_INSET_RATIO = 0.22f
|
|
56
|
+
private const val CHECKMARK_MID_OFFSET_RATIO = 0.05f
|
|
57
|
+
private const val BORDER_MIN_STROKE_WIDTH = 1f
|
|
58
|
+
private const val BORDER_STROKE_RATIO = 0.09f
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
private val boxPaint =
|
|
62
|
+
Paint(Paint.ANTI_ALIAS_FLAG).apply {
|
|
63
|
+
strokeCap = Paint.Cap.ROUND
|
|
64
|
+
strokeJoin = Paint.Join.ROUND
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
override fun getMarkerWidth(): Float = markerColumnWidth
|
|
68
|
+
|
|
69
|
+
override val baselineMarkerWidth: Float get() = checkboxColumnWidth
|
|
70
|
+
|
|
71
|
+
override fun drawMarker(
|
|
72
|
+
canvas: Canvas,
|
|
73
|
+
paint: Paint,
|
|
74
|
+
x: Int,
|
|
75
|
+
dir: Int,
|
|
76
|
+
top: Int,
|
|
77
|
+
baseline: Int,
|
|
78
|
+
bottom: Int,
|
|
79
|
+
layout: Layout?,
|
|
80
|
+
start: Int,
|
|
81
|
+
) {
|
|
82
|
+
val capHeight = -markerFontMetrics.ascent * CAP_HEIGHT_RATIO
|
|
83
|
+
val centerY = baseline - capHeight / HALF_DIVISOR
|
|
84
|
+
// Right-align the checkbox inside the reserved marker column so it hugs
|
|
85
|
+
// the gap before the text. At the default (markerColumnWidth ==
|
|
86
|
+
// checkboxSize) this is identical to the previous flush-left layout.
|
|
87
|
+
val centerX = x + (depth * marginLeft + ancestorMarkerOffset + markerColumnWidth - checkboxSize / HALF_DIVISOR) * dir
|
|
88
|
+
val half = checkboxSize / HALF_DIVISOR
|
|
89
|
+
rect.set(centerX - half, centerY - half, centerX + half, centerY + half)
|
|
90
|
+
|
|
91
|
+
if (isChecked) {
|
|
92
|
+
drawChecked(canvas, centerY)
|
|
93
|
+
} else {
|
|
94
|
+
drawUnchecked(canvas)
|
|
95
|
+
}
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
private fun drawChecked(
|
|
99
|
+
canvas: Canvas,
|
|
100
|
+
centerY: Float,
|
|
101
|
+
) {
|
|
102
|
+
boxPaint.apply {
|
|
103
|
+
style = Paint.Style.FILL
|
|
104
|
+
color = taskStyle.checkedColor
|
|
105
|
+
}
|
|
106
|
+
canvas.drawRoundRect(rect, cornerRadius, cornerRadius, boxPaint)
|
|
107
|
+
|
|
108
|
+
boxPaint.apply {
|
|
109
|
+
style = Paint.Style.STROKE
|
|
110
|
+
color = taskStyle.checkmarkColor
|
|
111
|
+
strokeWidth = maxOf(CHECKMARK_MIN_STROKE_WIDTH, checkboxSize * CHECKMARK_STROKE_RATIO)
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
val inset = checkboxSize * CHECKMARK_INSET_RATIO
|
|
115
|
+
val midOffset = checkboxSize * CHECKMARK_MID_OFFSET_RATIO
|
|
116
|
+
|
|
117
|
+
checkPath.run {
|
|
118
|
+
reset()
|
|
119
|
+
moveTo(rect.left + inset, centerY)
|
|
120
|
+
lineTo(rect.centerX() - midOffset, rect.bottom - inset)
|
|
121
|
+
lineTo(rect.right - inset, rect.top + inset)
|
|
122
|
+
}
|
|
123
|
+
canvas.drawPath(checkPath, boxPaint)
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
private fun drawUnchecked(canvas: Canvas) {
|
|
127
|
+
boxPaint.apply {
|
|
128
|
+
style = Paint.Style.STROKE
|
|
129
|
+
color = taskStyle.borderColor
|
|
130
|
+
strokeWidth = maxOf(BORDER_MIN_STROKE_WIDTH, checkboxSize * BORDER_STROKE_RATIO)
|
|
131
|
+
}
|
|
132
|
+
|
|
133
|
+
val halfStroke = boxPaint.strokeWidth / 2f
|
|
134
|
+
val insetRect =
|
|
135
|
+
RectF(
|
|
136
|
+
rect.left + halfStroke,
|
|
137
|
+
rect.top + halfStroke,
|
|
138
|
+
rect.right - halfStroke,
|
|
139
|
+
rect.bottom - halfStroke,
|
|
140
|
+
)
|
|
141
|
+
canvas.drawRoundRect(insetRect, cornerRadius, cornerRadius, boxPaint)
|
|
142
|
+
}
|
|
143
|
+
}
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
package com.renderrichtext.spans
|
|
2
|
+
|
|
3
|
+
import android.content.Context
|
|
4
|
+
import android.text.TextPaint
|
|
5
|
+
import android.text.style.MetricAffectingSpan
|
|
6
|
+
import com.renderrichtext.renderer.BlockStyle
|
|
7
|
+
import com.renderrichtext.utils.text.extensions.applyBlockStyleFont
|
|
8
|
+
|
|
9
|
+
class TextSpan(
|
|
10
|
+
private val blockStyle: BlockStyle,
|
|
11
|
+
private val context: Context,
|
|
12
|
+
) : MetricAffectingSpan() {
|
|
13
|
+
override fun updateDrawState(tp: TextPaint) {
|
|
14
|
+
applyBlockStyle(tp)
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
override fun updateMeasureState(tp: TextPaint) {
|
|
18
|
+
applyBlockStyle(tp)
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
private fun applyBlockStyle(tp: TextPaint) {
|
|
22
|
+
tp.textSize = blockStyle.fontSize
|
|
23
|
+
tp.color = blockStyle.color
|
|
24
|
+
tp.applyBlockStyleFont(blockStyle, context)
|
|
25
|
+
}
|
|
26
|
+
}
|