@mathers101/react-native-render-rich-text 0.0.0-stage → 0.1.10
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,92 @@
|
|
|
1
|
+
package com.renderrichtext.styles
|
|
2
|
+
|
|
3
|
+
import android.content.Context
|
|
4
|
+
import com.facebook.react.bridge.ColorPropConverter
|
|
5
|
+
import com.facebook.react.bridge.ReadableMap
|
|
6
|
+
import com.facebook.react.uimanager.PixelUtil
|
|
7
|
+
|
|
8
|
+
class StyleParser(
|
|
9
|
+
private val context: Context,
|
|
10
|
+
private val allowFontScaling: Boolean,
|
|
11
|
+
private val maxFontSizeMultiplier: Float,
|
|
12
|
+
) {
|
|
13
|
+
fun parseOptionalColor(
|
|
14
|
+
map: ReadableMap,
|
|
15
|
+
key: String,
|
|
16
|
+
): Int? {
|
|
17
|
+
if (!map.hasKey(key) || map.isNull(key)) {
|
|
18
|
+
return null
|
|
19
|
+
}
|
|
20
|
+
val colorValue = map.getDouble(key)
|
|
21
|
+
return ColorPropConverter.getColor(colorValue, context)
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
fun parseColor(
|
|
25
|
+
map: ReadableMap,
|
|
26
|
+
key: String,
|
|
27
|
+
): Int =
|
|
28
|
+
parseOptionalColor(map, key)
|
|
29
|
+
?: throw IllegalArgumentException("Color key '$key' is missing, null, or invalid")
|
|
30
|
+
|
|
31
|
+
fun parseOptionalDouble(
|
|
32
|
+
map: ReadableMap,
|
|
33
|
+
key: String,
|
|
34
|
+
default: Double = 0.0,
|
|
35
|
+
): Double =
|
|
36
|
+
if (map.hasKey(key) && !map.isNull(key)) {
|
|
37
|
+
map.getDouble(key)
|
|
38
|
+
} else {
|
|
39
|
+
default
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
fun parseOptionalInt(
|
|
43
|
+
map: ReadableMap,
|
|
44
|
+
key: String,
|
|
45
|
+
default: Int = 0,
|
|
46
|
+
): Int =
|
|
47
|
+
if (map.hasKey(key) && !map.isNull(key)) {
|
|
48
|
+
map.getInt(key)
|
|
49
|
+
} else {
|
|
50
|
+
default
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
fun parseString(
|
|
54
|
+
map: ReadableMap,
|
|
55
|
+
key: String,
|
|
56
|
+
default: String = "",
|
|
57
|
+
): String = map.getString(key) ?: default
|
|
58
|
+
|
|
59
|
+
fun parseBoolean(
|
|
60
|
+
map: ReadableMap,
|
|
61
|
+
key: String,
|
|
62
|
+
default: Boolean = false,
|
|
63
|
+
): Boolean =
|
|
64
|
+
if (map.hasKey(key) && !map.isNull(key)) {
|
|
65
|
+
map.getBoolean(key)
|
|
66
|
+
} else {
|
|
67
|
+
default
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
fun toPixelFromSP(value: Float): Float {
|
|
71
|
+
val metrics = context.resources.displayMetrics
|
|
72
|
+
val baseDensity = metrics.density
|
|
73
|
+
|
|
74
|
+
if (!allowFontScaling) {
|
|
75
|
+
return value * baseDensity
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
var fontScale = metrics.scaledDensity / baseDensity
|
|
79
|
+
if (maxFontSizeMultiplier >= 1.0f && fontScale > maxFontSizeMultiplier) {
|
|
80
|
+
fontScale = maxFontSizeMultiplier
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
return value * baseDensity * fontScale
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
fun toPixelFromDIP(value: Float): Float = PixelUtil.toPixelFromDIP(value)
|
|
87
|
+
|
|
88
|
+
fun parseTextAlign(
|
|
89
|
+
map: ReadableMap,
|
|
90
|
+
key: String,
|
|
91
|
+
): TextAlignment = TextAlignment.fromString(parseString(map, key, "left"))
|
|
92
|
+
}
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
package com.renderrichtext.styles
|
|
2
|
+
|
|
3
|
+
import com.facebook.react.bridge.ReadableMap
|
|
4
|
+
|
|
5
|
+
data class SubscriptStyle(
|
|
6
|
+
val fontScale: Float,
|
|
7
|
+
val baselineOffsetScale: Float,
|
|
8
|
+
) {
|
|
9
|
+
companion object {
|
|
10
|
+
fun fromReadableMap(map: ReadableMap): SubscriptStyle =
|
|
11
|
+
SubscriptStyle(
|
|
12
|
+
fontScale = map.getDouble("fontScale").toFloat(),
|
|
13
|
+
baselineOffsetScale = map.getDouble("baselineOffsetScale").toFloat(),
|
|
14
|
+
)
|
|
15
|
+
}
|
|
16
|
+
}
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
package com.renderrichtext.styles
|
|
2
|
+
|
|
3
|
+
import com.facebook.react.bridge.ReadableMap
|
|
4
|
+
|
|
5
|
+
data class SuperscriptStyle(
|
|
6
|
+
val fontScale: Float,
|
|
7
|
+
val baselineOffsetScale: Float,
|
|
8
|
+
) {
|
|
9
|
+
companion object {
|
|
10
|
+
fun fromReadableMap(map: ReadableMap): SuperscriptStyle =
|
|
11
|
+
SuperscriptStyle(
|
|
12
|
+
fontScale = map.getDouble("fontScale").toFloat(),
|
|
13
|
+
baselineOffsetScale = map.getDouble("baselineOffsetScale").toFloat(),
|
|
14
|
+
)
|
|
15
|
+
}
|
|
16
|
+
}
|
|
@@ -0,0 +1,75 @@
|
|
|
1
|
+
package com.renderrichtext.styles
|
|
2
|
+
|
|
3
|
+
import com.facebook.react.bridge.ReadableMap
|
|
4
|
+
|
|
5
|
+
data class TableStyle(
|
|
6
|
+
override val fontSize: Float,
|
|
7
|
+
override val fontFamily: String,
|
|
8
|
+
override val fontWeight: String,
|
|
9
|
+
override val color: Int,
|
|
10
|
+
override val marginTop: Float,
|
|
11
|
+
override val marginBottom: Float,
|
|
12
|
+
override val lineHeight: Float,
|
|
13
|
+
val headerFontFamily: String,
|
|
14
|
+
val headerBackgroundColor: Int,
|
|
15
|
+
val headerTextColor: Int,
|
|
16
|
+
val rowEvenBackgroundColor: Int,
|
|
17
|
+
val rowOddBackgroundColor: Int,
|
|
18
|
+
val borderColor: Int,
|
|
19
|
+
val borderWidth: Float,
|
|
20
|
+
val borderRadius: Float,
|
|
21
|
+
val cellPaddingHorizontal: Float,
|
|
22
|
+
val cellPaddingVertical: Float,
|
|
23
|
+
val horizontalOverflow: Float,
|
|
24
|
+
val align: String,
|
|
25
|
+
) : BaseBlockStyle {
|
|
26
|
+
companion object {
|
|
27
|
+
fun fromReadableMap(
|
|
28
|
+
map: ReadableMap,
|
|
29
|
+
parser: StyleParser,
|
|
30
|
+
): TableStyle {
|
|
31
|
+
val fontSize = parser.toPixelFromSP(map.getDouble("fontSize").toFloat())
|
|
32
|
+
val fontFamily = parser.parseString(map, "fontFamily")
|
|
33
|
+
val fontWeight = parser.parseString(map, "fontWeight", "normal")
|
|
34
|
+
val color = parser.parseColor(map, "color")
|
|
35
|
+
val marginTop = parser.toPixelFromDIP(map.getDouble("marginTop").toFloat())
|
|
36
|
+
val marginBottom = parser.toPixelFromDIP(map.getDouble("marginBottom").toFloat())
|
|
37
|
+
val lineHeightRaw = map.getDouble("lineHeight").toFloat()
|
|
38
|
+
val lineHeight = if (lineHeightRaw > 0f) parser.toPixelFromSP(lineHeightRaw) else 0f
|
|
39
|
+
val headerFontFamily = parser.parseString(map, "headerFontFamily")
|
|
40
|
+
val headerBackgroundColor = parser.parseColor(map, "headerBackgroundColor")
|
|
41
|
+
val headerTextColor = parser.parseColor(map, "headerTextColor")
|
|
42
|
+
val rowEvenBackgroundColor = parser.parseColor(map, "rowEvenBackgroundColor")
|
|
43
|
+
val rowOddBackgroundColor = parser.parseColor(map, "rowOddBackgroundColor")
|
|
44
|
+
val borderColor = parser.parseColor(map, "borderColor")
|
|
45
|
+
val borderWidth = parser.toPixelFromDIP(map.getDouble("borderWidth").toFloat())
|
|
46
|
+
val borderRadius = parser.toPixelFromDIP(map.getDouble("borderRadius").toFloat())
|
|
47
|
+
val cellPaddingHorizontal = parser.toPixelFromDIP(map.getDouble("cellPaddingHorizontal").toFloat())
|
|
48
|
+
val cellPaddingVertical = parser.toPixelFromDIP(map.getDouble("cellPaddingVertical").toFloat())
|
|
49
|
+
val horizontalOverflow = parser.toPixelFromDIP(map.getDouble("horizontalOverflow").toFloat())
|
|
50
|
+
val align = parser.parseString(map, "align")
|
|
51
|
+
|
|
52
|
+
return TableStyle(
|
|
53
|
+
fontSize = fontSize,
|
|
54
|
+
fontFamily = fontFamily,
|
|
55
|
+
fontWeight = fontWeight,
|
|
56
|
+
color = color,
|
|
57
|
+
marginTop = marginTop,
|
|
58
|
+
marginBottom = marginBottom,
|
|
59
|
+
lineHeight = lineHeight,
|
|
60
|
+
headerFontFamily = headerFontFamily,
|
|
61
|
+
headerBackgroundColor = headerBackgroundColor,
|
|
62
|
+
headerTextColor = headerTextColor,
|
|
63
|
+
rowEvenBackgroundColor = rowEvenBackgroundColor,
|
|
64
|
+
rowOddBackgroundColor = rowOddBackgroundColor,
|
|
65
|
+
borderColor = borderColor,
|
|
66
|
+
borderWidth = borderWidth,
|
|
67
|
+
borderRadius = borderRadius,
|
|
68
|
+
cellPaddingHorizontal = cellPaddingHorizontal,
|
|
69
|
+
cellPaddingVertical = cellPaddingVertical,
|
|
70
|
+
horizontalOverflow = horizontalOverflow,
|
|
71
|
+
align = align,
|
|
72
|
+
)
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
}
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
package com.renderrichtext.styles
|
|
2
|
+
|
|
3
|
+
import com.facebook.react.bridge.ReadableMap
|
|
4
|
+
|
|
5
|
+
data class TaskListStyle(
|
|
6
|
+
val checkedColor: Int,
|
|
7
|
+
val borderColor: Int,
|
|
8
|
+
val checkboxSize: Float,
|
|
9
|
+
val checkboxBorderRadius: Float,
|
|
10
|
+
val checkmarkColor: Int,
|
|
11
|
+
val checkedTextColor: Int,
|
|
12
|
+
val checkedStrikethrough: Boolean,
|
|
13
|
+
) {
|
|
14
|
+
companion object {
|
|
15
|
+
fun fromReadableMap(
|
|
16
|
+
map: ReadableMap,
|
|
17
|
+
parser: StyleParser,
|
|
18
|
+
): TaskListStyle =
|
|
19
|
+
TaskListStyle(
|
|
20
|
+
checkedColor = parser.parseColor(map, "checkedColor"),
|
|
21
|
+
borderColor = parser.parseColor(map, "borderColor"),
|
|
22
|
+
checkboxSize = parser.toPixelFromDIP(map.getDouble("checkboxSize").toFloat()),
|
|
23
|
+
checkboxBorderRadius = parser.toPixelFromDIP(map.getDouble("checkboxBorderRadius").toFloat()),
|
|
24
|
+
checkmarkColor = parser.parseColor(map, "checkmarkColor"),
|
|
25
|
+
checkedTextColor = parser.parseColor(map, "checkedTextColor"),
|
|
26
|
+
checkedStrikethrough = map.getBoolean("checkedStrikethrough"),
|
|
27
|
+
)
|
|
28
|
+
}
|
|
29
|
+
}
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
package com.renderrichtext.styles
|
|
2
|
+
|
|
3
|
+
import android.text.Layout
|
|
4
|
+
|
|
5
|
+
enum class TextAlignment(
|
|
6
|
+
val layoutAlignment: Layout.Alignment,
|
|
7
|
+
val needsJustify: Boolean,
|
|
8
|
+
) {
|
|
9
|
+
LEFT(Layout.Alignment.ALIGN_NORMAL, false),
|
|
10
|
+
CENTER(Layout.Alignment.ALIGN_CENTER, false),
|
|
11
|
+
RIGHT(Layout.Alignment.ALIGN_OPPOSITE, false),
|
|
12
|
+
JUSTIFY(Layout.Alignment.ALIGN_NORMAL, true),
|
|
13
|
+
AUTO(Layout.Alignment.ALIGN_NORMAL, false),
|
|
14
|
+
;
|
|
15
|
+
|
|
16
|
+
/**
|
|
17
|
+
* Whether an AlignmentSpan is needed.
|
|
18
|
+
* Only CENTER and RIGHT need explicit spans; LEFT/AUTO use default, JUSTIFY is handled at TextView level.
|
|
19
|
+
*/
|
|
20
|
+
val needsAlignmentSpan: Boolean get() = this == CENTER || this == RIGHT
|
|
21
|
+
|
|
22
|
+
companion object {
|
|
23
|
+
fun fromString(value: String): TextAlignment =
|
|
24
|
+
when (value.lowercase()) {
|
|
25
|
+
"center" -> CENTER
|
|
26
|
+
"right" -> RIGHT
|
|
27
|
+
"justify" -> JUSTIFY
|
|
28
|
+
"auto" -> AUTO
|
|
29
|
+
else -> LEFT
|
|
30
|
+
}
|
|
31
|
+
}
|
|
32
|
+
}
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
package com.renderrichtext.styles
|
|
2
|
+
|
|
3
|
+
import com.facebook.react.bridge.ReadableMap
|
|
4
|
+
|
|
5
|
+
data class ThematicBreakStyle(
|
|
6
|
+
val color: Int,
|
|
7
|
+
val height: Float,
|
|
8
|
+
val marginTop: Float,
|
|
9
|
+
val marginBottom: Float,
|
|
10
|
+
) {
|
|
11
|
+
companion object {
|
|
12
|
+
fun fromReadableMap(
|
|
13
|
+
map: ReadableMap,
|
|
14
|
+
parser: StyleParser,
|
|
15
|
+
): ThematicBreakStyle {
|
|
16
|
+
val color = parser.parseColor(map, "color")
|
|
17
|
+
val height = parser.toPixelFromDIP(map.getDouble("height").toFloat())
|
|
18
|
+
val marginTop = parser.toPixelFromDIP(map.getDouble("marginTop").toFloat())
|
|
19
|
+
val marginBottom = parser.toPixelFromDIP(map.getDouble("marginBottom").toFloat())
|
|
20
|
+
return ThematicBreakStyle(color, height, marginTop, marginBottom)
|
|
21
|
+
}
|
|
22
|
+
}
|
|
23
|
+
}
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
package com.renderrichtext.styles
|
|
2
|
+
|
|
3
|
+
import com.facebook.react.bridge.ReadableMap
|
|
4
|
+
|
|
5
|
+
data class UnderlineStyle(
|
|
6
|
+
val color: Int,
|
|
7
|
+
) {
|
|
8
|
+
companion object {
|
|
9
|
+
fun fromReadableMap(
|
|
10
|
+
map: ReadableMap,
|
|
11
|
+
parser: StyleParser,
|
|
12
|
+
): UnderlineStyle {
|
|
13
|
+
val color = parser.parseColor(map, "color")
|
|
14
|
+
return UnderlineStyle(color)
|
|
15
|
+
}
|
|
16
|
+
}
|
|
17
|
+
}
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
package com.renderrichtext.styles
|
|
2
|
+
|
|
3
|
+
import com.facebook.react.bridge.ReadableMap
|
|
4
|
+
|
|
5
|
+
data class VideoStyle(
|
|
6
|
+
val marginTop: Float,
|
|
7
|
+
val marginBottom: Float,
|
|
8
|
+
val borderRadius: Float,
|
|
9
|
+
val aspectRatio: Float,
|
|
10
|
+
val backgroundColor: Int,
|
|
11
|
+
) {
|
|
12
|
+
/** Aspect ratio guaranteed to be positive. Falls back to 16:9 if the raw value is ≤ 0. */
|
|
13
|
+
val resolvedAspectRatio: Float
|
|
14
|
+
get() = if (aspectRatio > 0f) aspectRatio else DEFAULT_ASPECT_RATIO
|
|
15
|
+
|
|
16
|
+
companion object {
|
|
17
|
+
private const val DEFAULT_ASPECT_RATIO = 16f / 9f
|
|
18
|
+
|
|
19
|
+
fun fromReadableMap(
|
|
20
|
+
map: ReadableMap,
|
|
21
|
+
parser: StyleParser,
|
|
22
|
+
): VideoStyle {
|
|
23
|
+
val marginTop = parser.toPixelFromDIP(map.getDouble("marginTop").toFloat())
|
|
24
|
+
val marginBottom = parser.toPixelFromDIP(map.getDouble("marginBottom").toFloat())
|
|
25
|
+
val borderRadius = parser.toPixelFromDIP(map.getDouble("borderRadius").toFloat())
|
|
26
|
+
val aspectRatio = map.getDouble("aspectRatio").toFloat()
|
|
27
|
+
val backgroundColor = parser.parseColor(map, "backgroundColor")
|
|
28
|
+
return VideoStyle(marginTop, marginBottom, borderRadius, aspectRatio, backgroundColor)
|
|
29
|
+
}
|
|
30
|
+
}
|
|
31
|
+
}
|
|
@@ -0,0 +1,86 @@
|
|
|
1
|
+
package com.renderrichtext.utils.common
|
|
2
|
+
|
|
3
|
+
import android.view.View
|
|
4
|
+
import com.facebook.react.bridge.ColorPropConverter
|
|
5
|
+
import com.facebook.react.uimanager.BackgroundStyleApplicator
|
|
6
|
+
import com.facebook.react.uimanager.LengthPercentage
|
|
7
|
+
import com.facebook.react.uimanager.ReactStylesDiffMap
|
|
8
|
+
import com.facebook.react.uimanager.style.BorderRadiusProp
|
|
9
|
+
import com.facebook.react.uimanager.style.BorderStyle
|
|
10
|
+
import com.facebook.react.uimanager.style.LogicalEdge
|
|
11
|
+
|
|
12
|
+
// BaseViewManagerDelegate (used by our SimpleViewManagers) ignores border
|
|
13
|
+
// width/color/style and no-ops borderRadius, so `containerStyle` borders vanish on
|
|
14
|
+
// Android. Replay them via BackgroundStyleApplicator like ReactViewManager does.
|
|
15
|
+
// Call after super.updateProperties so the composite background drawable exists.
|
|
16
|
+
fun applyReactBorderProps(
|
|
17
|
+
view: View,
|
|
18
|
+
props: ReactStylesDiffMap,
|
|
19
|
+
) {
|
|
20
|
+
for ((name, edge) in BORDER_WIDTH_EDGES) {
|
|
21
|
+
if (!props.hasKey(name)) continue
|
|
22
|
+
val width = if (props.isNull(name)) null else props.getFloat(name, Float.NaN).takeUnless { it.isNaN() }
|
|
23
|
+
BackgroundStyleApplicator.setBorderWidth(view, edge, width)
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
if (BORDER_COLOR_EDGES.keys.any { props.hasKey(it) }) {
|
|
27
|
+
val rawProps = props.toMap()
|
|
28
|
+
for ((name, edge) in BORDER_COLOR_EDGES) {
|
|
29
|
+
if (!props.hasKey(name)) continue
|
|
30
|
+
val color = if (props.isNull(name)) null else ColorPropConverter.getColor(rawProps[name], view.context)
|
|
31
|
+
BackgroundStyleApplicator.setBorderColor(view, edge, color)
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
if (props.hasKey("borderStyle")) {
|
|
36
|
+
val style = if (props.isNull("borderStyle")) null else BorderStyle.fromString(props.getString("borderStyle") ?: "")
|
|
37
|
+
BackgroundStyleApplicator.setBorderStyle(view, style)
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
// Radius last, so the border drawable created above already exists and picks
|
|
41
|
+
// up the rounded corners.
|
|
42
|
+
for ((name, corner) in BORDER_RADIUS_PROPS) {
|
|
43
|
+
if (!props.hasKey(name)) continue
|
|
44
|
+
val radius = if (props.isNull(name)) null else LengthPercentage.setFromDynamic(props.getDynamic(name))
|
|
45
|
+
BackgroundStyleApplicator.setBorderRadius(view, corner, radius)
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
private val BORDER_WIDTH_EDGES =
|
|
50
|
+
linkedMapOf(
|
|
51
|
+
"borderWidth" to LogicalEdge.ALL,
|
|
52
|
+
"borderLeftWidth" to LogicalEdge.LEFT,
|
|
53
|
+
"borderRightWidth" to LogicalEdge.RIGHT,
|
|
54
|
+
"borderTopWidth" to LogicalEdge.TOP,
|
|
55
|
+
"borderBottomWidth" to LogicalEdge.BOTTOM,
|
|
56
|
+
"borderStartWidth" to LogicalEdge.START,
|
|
57
|
+
"borderEndWidth" to LogicalEdge.END,
|
|
58
|
+
)
|
|
59
|
+
|
|
60
|
+
private val BORDER_COLOR_EDGES =
|
|
61
|
+
linkedMapOf(
|
|
62
|
+
"borderColor" to LogicalEdge.ALL,
|
|
63
|
+
"borderLeftColor" to LogicalEdge.LEFT,
|
|
64
|
+
"borderRightColor" to LogicalEdge.RIGHT,
|
|
65
|
+
"borderTopColor" to LogicalEdge.TOP,
|
|
66
|
+
"borderBottomColor" to LogicalEdge.BOTTOM,
|
|
67
|
+
"borderStartColor" to LogicalEdge.START,
|
|
68
|
+
"borderEndColor" to LogicalEdge.END,
|
|
69
|
+
)
|
|
70
|
+
|
|
71
|
+
private val BORDER_RADIUS_PROPS =
|
|
72
|
+
linkedMapOf(
|
|
73
|
+
"borderRadius" to BorderRadiusProp.BORDER_RADIUS,
|
|
74
|
+
"borderTopLeftRadius" to BorderRadiusProp.BORDER_TOP_LEFT_RADIUS,
|
|
75
|
+
"borderTopRightRadius" to BorderRadiusProp.BORDER_TOP_RIGHT_RADIUS,
|
|
76
|
+
"borderBottomRightRadius" to BorderRadiusProp.BORDER_BOTTOM_RIGHT_RADIUS,
|
|
77
|
+
"borderBottomLeftRadius" to BorderRadiusProp.BORDER_BOTTOM_LEFT_RADIUS,
|
|
78
|
+
"borderTopStartRadius" to BorderRadiusProp.BORDER_TOP_START_RADIUS,
|
|
79
|
+
"borderTopEndRadius" to BorderRadiusProp.BORDER_TOP_END_RADIUS,
|
|
80
|
+
"borderBottomStartRadius" to BorderRadiusProp.BORDER_BOTTOM_START_RADIUS,
|
|
81
|
+
"borderBottomEndRadius" to BorderRadiusProp.BORDER_BOTTOM_END_RADIUS,
|
|
82
|
+
"borderEndEndRadius" to BorderRadiusProp.BORDER_END_END_RADIUS,
|
|
83
|
+
"borderEndStartRadius" to BorderRadiusProp.BORDER_END_START_RADIUS,
|
|
84
|
+
"borderStartEndRadius" to BorderRadiusProp.BORDER_START_END_RADIUS,
|
|
85
|
+
"borderStartStartRadius" to BorderRadiusProp.BORDER_START_START_RADIUS,
|
|
86
|
+
)
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
package com.renderrichtext.utils.common
|
|
2
|
+
|
|
3
|
+
import android.text.Layout
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* Resolves a textBreakStrategy prop value (string) to the integer constant used
|
|
7
|
+
* by StaticLayout.Builder.setBreakStrategy() and TextView.setBreakStrategy().
|
|
8
|
+
*
|
|
9
|
+
* Stateless on purpose: textBreakStrategy is a per-view prop. Storage lives in
|
|
10
|
+
* [com.renderrichtext.MeasurementStore] (per viewId), and each
|
|
11
|
+
* view applies the resolved value to its own TextView. Both measurement and
|
|
12
|
+
* render paths must use the same value — mismatch causes measured line count
|
|
13
|
+
* to differ from the rendered line count, sizing the view incorrectly and
|
|
14
|
+
* causing ScrollingMovementMethod (inherited via LinkMovementMethod) to
|
|
15
|
+
* silently scroll the overflow.
|
|
16
|
+
*
|
|
17
|
+
* Note: call sites in StaticLayout.Builder suppress "WrongConstant" lint. This is
|
|
18
|
+
* intentional - Layout.BREAK_STRATEGY_SIMPLE and LineBreaker.BREAK_STRATEGY_SIMPLE
|
|
19
|
+
* are the same integer (0), but the @IntDef annotation on StaticLayout.Builder
|
|
20
|
+
* .setBreakStrategy() was changed from Layout.* to LineBreaker.* in API 29.
|
|
21
|
+
* The suppression is safe; the Layout.* constants share the same integer values.
|
|
22
|
+
*/
|
|
23
|
+
object BreakStrategyUtils {
|
|
24
|
+
const val DEFAULT_STRATEGY = "highQuality"
|
|
25
|
+
|
|
26
|
+
fun resolveBreakStrategy(strategy: String?): Int =
|
|
27
|
+
when (strategy) {
|
|
28
|
+
"simple" -> Layout.BREAK_STRATEGY_SIMPLE
|
|
29
|
+
"balanced" -> Layout.BREAK_STRATEGY_BALANCED
|
|
30
|
+
else -> Layout.BREAK_STRATEGY_HIGH_QUALITY
|
|
31
|
+
}
|
|
32
|
+
}
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
package com.renderrichtext.utils.common
|
|
2
|
+
|
|
3
|
+
import android.text.Spannable
|
|
4
|
+
import com.renderrichtext.styles.CodeBlockStyle
|
|
5
|
+
|
|
6
|
+
/**
|
|
7
|
+
* Syntax highlighting is not part of this library. Code blocks stay plain
|
|
8
|
+
* monospace; the language attribute is kept on the node and not colored.
|
|
9
|
+
*/
|
|
10
|
+
enum class HighlightTokenType {
|
|
11
|
+
Keyword,
|
|
12
|
+
Operator,
|
|
13
|
+
Punctuation,
|
|
14
|
+
String,
|
|
15
|
+
Number,
|
|
16
|
+
Constant,
|
|
17
|
+
Comment,
|
|
18
|
+
Function,
|
|
19
|
+
Type,
|
|
20
|
+
Variable,
|
|
21
|
+
Property,
|
|
22
|
+
Tag,
|
|
23
|
+
Attribute,
|
|
24
|
+
Embedded,
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
object CodeBlockHighlighter {
|
|
28
|
+
fun highlight(
|
|
29
|
+
target: Spannable,
|
|
30
|
+
code: String,
|
|
31
|
+
language: String?,
|
|
32
|
+
style: CodeBlockStyle,
|
|
33
|
+
offset: Int = 0,
|
|
34
|
+
) {
|
|
35
|
+
}
|
|
36
|
+
}
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
package com.renderrichtext.utils.common
|
|
2
|
+
|
|
3
|
+
import com.renderrichtext.parser.TiptapASTNode
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* Shared code block node semantics, used by both tiptap flavors so the
|
|
7
|
+
* meaning of a CodeBlock AST node (its text, language, fence) is defined in
|
|
8
|
+
* one place. Language display names come from the shared C++ core
|
|
9
|
+
* (cpp/highlight/CodeBlockLanguages.hpp) so all platforms label fences
|
|
10
|
+
* identically; when the native library is unavailable the raw fence string
|
|
11
|
+
* is shown instead.
|
|
12
|
+
*/
|
|
13
|
+
object CodeBlockNode {
|
|
14
|
+
fun extractCode(node: TiptapASTNode): String {
|
|
15
|
+
val builder = StringBuilder()
|
|
16
|
+
|
|
17
|
+
fun append(current: TiptapASTNode) {
|
|
18
|
+
builder.append(current.content)
|
|
19
|
+
current.children.forEach { append(it) }
|
|
20
|
+
}
|
|
21
|
+
append(node)
|
|
22
|
+
return builder.toString().trimEnd('\n')
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
fun language(node: TiptapASTNode): String? = node.getAttribute("language")?.takeIf { it.isNotEmpty() }
|
|
26
|
+
|
|
27
|
+
fun fenceChar(node: TiptapASTNode): String = node.getAttribute("fenceChar")?.takeIf { it.isNotEmpty() } ?: "`"
|
|
28
|
+
|
|
29
|
+
fun fencedTiptap(
|
|
30
|
+
code: String,
|
|
31
|
+
language: String?,
|
|
32
|
+
fenceChar: String,
|
|
33
|
+
): String {
|
|
34
|
+
val fence = fenceChar.repeat(3)
|
|
35
|
+
return "$fence${language.orEmpty()}\n$code\n$fence"
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
fun displayLanguageName(language: String?): String {
|
|
39
|
+
if (language.isNullOrEmpty()) return ""
|
|
40
|
+
return language
|
|
41
|
+
}
|
|
42
|
+
}
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
package com.renderrichtext.utils.common
|
|
2
|
+
|
|
3
|
+
import android.text.TextUtils.TruncateAt
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* Resolves an ellipsizeMode prop value (string) to the TruncateAt used by
|
|
7
|
+
* StaticLayout.Builder.setEllipsize() and TextView.setEllipsize().
|
|
8
|
+
*
|
|
9
|
+
* "clip" maps to null: with maxLines set, the layout still truncates but draws
|
|
10
|
+
* no ellipsis glyph. Mirrors React Native's TextAttributeProps.getEllipsizeMode.
|
|
11
|
+
*
|
|
12
|
+
* Stateless like [BreakStrategyUtils]: the mode is a per-view prop stored per
|
|
13
|
+
* viewId in [com.renderrichtext.MeasurementStore]. Measurement and
|
|
14
|
+
* render paths must resolve the same value, or the measured line count diverges
|
|
15
|
+
* from the rendered one and the view is sized incorrectly.
|
|
16
|
+
*/
|
|
17
|
+
object EllipsizeUtils {
|
|
18
|
+
const val DEFAULT_MODE = "tail"
|
|
19
|
+
|
|
20
|
+
fun resolveTruncateAt(mode: String?): TruncateAt? =
|
|
21
|
+
when (mode) {
|
|
22
|
+
"head" -> TruncateAt.START
|
|
23
|
+
"middle" -> TruncateAt.MIDDLE
|
|
24
|
+
"clip" -> null
|
|
25
|
+
else -> TruncateAt.END
|
|
26
|
+
}
|
|
27
|
+
}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
package com.renderrichtext.utils.common
|
|
2
|
+
|
|
3
|
+
import android.view.View
|
|
4
|
+
import com.renderrichtext.EnrichedTiptapText
|
|
5
|
+
|
|
6
|
+
fun View.findEnrichedTiptapTextAncestor(): EnrichedTiptapText? {
|
|
7
|
+
var current: android.view.ViewParent? = parent
|
|
8
|
+
while (current != null && current !is EnrichedTiptapText) current = current.parent
|
|
9
|
+
return current as? EnrichedTiptapText
|
|
10
|
+
}
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
package com.renderrichtext.utils.common
|
|
2
|
+
|
|
3
|
+
import com.renderrichtext.BuildConfig
|
|
4
|
+
|
|
5
|
+
object FeatureFlags {
|
|
6
|
+
const val IS_MATH_ENABLED: Boolean = BuildConfig.ENABLE_MATH
|
|
7
|
+
const val IS_VIDEO_ENABLED: Boolean = BuildConfig.ENABLE_VIDEO
|
|
8
|
+
const val IS_CODE_HIGHLIGHT_ENABLED: Boolean = BuildConfig.ENABLE_CODE_HIGHLIGHT
|
|
9
|
+
}
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
package com.renderrichtext.utils.common
|
|
2
|
+
|
|
3
|
+
import com.facebook.react.bridge.ReadableMap
|
|
4
|
+
|
|
5
|
+
data class LinkRecognition(
|
|
6
|
+
val text: LinkRegexConfig? = null,
|
|
7
|
+
val inlineCode: LinkRegexConfig? = null,
|
|
8
|
+
) {
|
|
9
|
+
companion object {
|
|
10
|
+
val NONE = LinkRecognition()
|
|
11
|
+
}
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
internal fun parseLinkRecognition(map: ReadableMap?): LinkRecognition {
|
|
15
|
+
if (map == null) return LinkRecognition.NONE
|
|
16
|
+
return LinkRecognition(
|
|
17
|
+
text = parseLinkRegexConfig(map.getMapOrNull("text")),
|
|
18
|
+
inlineCode = parseLinkRegexConfig(map.getMapOrNull("inlineCode")),
|
|
19
|
+
)
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
internal fun parseLinkRegexConfig(map: ReadableMap?): LinkRegexConfig? {
|
|
23
|
+
if (map == null) return null
|
|
24
|
+
return LinkRegexConfig(
|
|
25
|
+
pattern = if (map.hasKey("pattern")) map.getString("pattern") ?: "" else "",
|
|
26
|
+
caseInsensitive = map.hasKey("caseInsensitive") && map.getBoolean("caseInsensitive"),
|
|
27
|
+
dotAll = map.hasKey("dotAll") && map.getBoolean("dotAll"),
|
|
28
|
+
isDisabled = !map.hasKey("isDisabled") || map.getBoolean("isDisabled"),
|
|
29
|
+
isDefault = map.hasKey("isDefault") && map.getBoolean("isDefault"),
|
|
30
|
+
)
|
|
31
|
+
}
|
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
package com.renderrichtext.utils.common
|
|
2
|
+
|
|
3
|
+
import java.util.regex.Pattern
|
|
4
|
+
import java.util.regex.PatternSyntaxException
|
|
5
|
+
|
|
6
|
+
/** A regex sent from JS. Equal configs share compiled patterns. */
|
|
7
|
+
data class LinkRegexConfig(
|
|
8
|
+
val pattern: String,
|
|
9
|
+
val caseInsensitive: Boolean,
|
|
10
|
+
val dotAll: Boolean,
|
|
11
|
+
val isDisabled: Boolean,
|
|
12
|
+
val isDefault: Boolean,
|
|
13
|
+
) {
|
|
14
|
+
private val isActive: Boolean
|
|
15
|
+
get() = !isDisabled && !isDefault && pattern.isNotEmpty()
|
|
16
|
+
|
|
17
|
+
/** Null when inactive or invalid. */
|
|
18
|
+
val compiled: Pattern?
|
|
19
|
+
get() = if (isActive) compiledPattern(pattern, flags) else null
|
|
20
|
+
|
|
21
|
+
/** Anchored to the whole string, for inline-code spans. */
|
|
22
|
+
val compiledWholeSpan: Pattern?
|
|
23
|
+
get() = if (isActive) compiledPattern("\\A(?:$pattern)\\z", flags) else null
|
|
24
|
+
|
|
25
|
+
private val flags: Int
|
|
26
|
+
get() = (if (caseInsensitive) Pattern.CASE_INSENSITIVE else 0) or (if (dotAll) Pattern.DOTALL else 0)
|
|
27
|
+
|
|
28
|
+
private companion object {
|
|
29
|
+
private const val MAX_CACHED_PATTERNS = 64
|
|
30
|
+
private val invalid = Pattern.compile("(?!)")
|
|
31
|
+
|
|
32
|
+
// Bounded LRU keyed by flags and source.
|
|
33
|
+
private val cache =
|
|
34
|
+
object : LinkedHashMap<String, Pattern>(MAX_CACHED_PATTERNS, 0.75f, true) {
|
|
35
|
+
override fun removeEldestEntry(eldest: MutableMap.MutableEntry<String, Pattern>): Boolean = size > MAX_CACHED_PATTERNS
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
@Synchronized
|
|
39
|
+
fun compiledPattern(
|
|
40
|
+
source: String,
|
|
41
|
+
flags: Int,
|
|
42
|
+
): Pattern? {
|
|
43
|
+
val key = "$flags\u0000$source"
|
|
44
|
+
val cached = cache[key]
|
|
45
|
+
if (cached != null) return cached.takeUnless { it === invalid }
|
|
46
|
+
val compiled =
|
|
47
|
+
try {
|
|
48
|
+
Pattern.compile(source, flags)
|
|
49
|
+
} catch (_: PatternSyntaxException) {
|
|
50
|
+
invalid
|
|
51
|
+
}
|
|
52
|
+
cache[key] = compiled
|
|
53
|
+
return compiled.takeUnless { it === invalid }
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
}
|