@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,35 @@
|
|
|
1
|
+
#import <Foundation/Foundation.h>
|
|
2
|
+
|
|
3
|
+
@class RenderContext;
|
|
4
|
+
|
|
5
|
+
NS_ASSUME_NONNULL_BEGIN
|
|
6
|
+
|
|
7
|
+
/**
|
|
8
|
+
* Container for accessibility-related data extracted from RenderContext.
|
|
9
|
+
* Used by TiptapAccessibilityElementBuilder to build VoiceOver elements.
|
|
10
|
+
*/
|
|
11
|
+
@interface AccessibilityInfo : NSObject
|
|
12
|
+
|
|
13
|
+
// Headings
|
|
14
|
+
@property (nonatomic, copy, readonly) NSArray<NSValue *> *headingRanges;
|
|
15
|
+
@property (nonatomic, copy, readonly) NSArray<NSNumber *> *headingLevels;
|
|
16
|
+
|
|
17
|
+
// Links
|
|
18
|
+
@property (nonatomic, copy, readonly) NSArray<NSValue *> *linkRanges;
|
|
19
|
+
@property (nonatomic, copy, readonly) NSArray<NSString *> *linkURLs;
|
|
20
|
+
|
|
21
|
+
// Images
|
|
22
|
+
@property (nonatomic, copy, readonly) NSArray<NSValue *> *imageRanges;
|
|
23
|
+
@property (nonatomic, copy, readonly) NSArray<NSString *> *imageAltTexts;
|
|
24
|
+
|
|
25
|
+
// List items
|
|
26
|
+
@property (nonatomic, copy, readonly) NSArray<NSValue *> *listItemRanges;
|
|
27
|
+
@property (nonatomic, copy, readonly) NSArray<NSNumber *> *listItemPositions;
|
|
28
|
+
@property (nonatomic, copy, readonly) NSArray<NSNumber *> *listItemDepths;
|
|
29
|
+
@property (nonatomic, copy, readonly) NSArray<NSNumber *> *listItemOrdered; // YES = ordered, NO = bullet
|
|
30
|
+
|
|
31
|
+
+ (instancetype)infoFromContext:(RenderContext *)context;
|
|
32
|
+
|
|
33
|
+
@end
|
|
34
|
+
|
|
35
|
+
NS_ASSUME_NONNULL_END
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
#import "AccessibilityInfo.h"
|
|
2
|
+
#import "RenderContext.h"
|
|
3
|
+
|
|
4
|
+
@implementation AccessibilityInfo
|
|
5
|
+
|
|
6
|
+
+ (instancetype)infoFromContext:(RenderContext *)context
|
|
7
|
+
{
|
|
8
|
+
AccessibilityInfo *info = [[AccessibilityInfo alloc] init];
|
|
9
|
+
if (info) {
|
|
10
|
+
info->_headingRanges = [context.headingRanges copy];
|
|
11
|
+
info->_headingLevels = [context.headingLevels copy];
|
|
12
|
+
info->_linkRanges = [context.linkRanges copy];
|
|
13
|
+
info->_linkURLs = [context.linkURLs copy];
|
|
14
|
+
info->_imageRanges = [context.imageRanges copy];
|
|
15
|
+
info->_imageAltTexts = [context.imageAltTexts copy];
|
|
16
|
+
info->_listItemRanges = [context.listItemRanges copy];
|
|
17
|
+
info->_listItemPositions = [context.listItemPositions copy];
|
|
18
|
+
info->_listItemDepths = [context.listItemDepths copy];
|
|
19
|
+
info->_listItemOrdered = [context.listItemOrdered copy];
|
|
20
|
+
}
|
|
21
|
+
return info;
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
@end
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
#pragma once
|
|
2
|
+
#import "ENRMUIKit.h"
|
|
3
|
+
#import "StyleConfig.h"
|
|
4
|
+
|
|
5
|
+
NS_ASSUME_NONNULL_BEGIN
|
|
6
|
+
|
|
7
|
+
extern NSString *const BlockquoteDepthAttributeName;
|
|
8
|
+
extern NSString *const BlockquoteBackgroundColorAttributeName;
|
|
9
|
+
extern NSString *const BlockquoteSpacerAttributeName;
|
|
10
|
+
|
|
11
|
+
static inline CGFloat blockquoteIndentForDepth(NSInteger depth, CGFloat levelSpacing)
|
|
12
|
+
{
|
|
13
|
+
return depth * levelSpacing;
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
@interface BlockquoteBorder : NSObject
|
|
17
|
+
|
|
18
|
+
- (instancetype)initWithConfig:(StyleConfig *)config;
|
|
19
|
+
- (void)drawBordersForGlyphRange:(NSRange)glyphsToShow
|
|
20
|
+
layoutManager:(NSLayoutManager *)layoutManager
|
|
21
|
+
textContainer:(NSTextContainer *)textContainer
|
|
22
|
+
atPoint:(CGPoint)origin;
|
|
23
|
+
|
|
24
|
+
@end
|
|
25
|
+
|
|
26
|
+
NS_ASSUME_NONNULL_END
|
|
@@ -0,0 +1,294 @@
|
|
|
1
|
+
#import "BlockquoteBorder.h"
|
|
2
|
+
#import "ParagraphStyleUtils.h"
|
|
3
|
+
#import "StyleConfig.h"
|
|
4
|
+
|
|
5
|
+
// Attribute constants for identifying blockquote segments in text storage
|
|
6
|
+
NSString *const BlockquoteDepthAttributeName = @"BlockquoteDepth";
|
|
7
|
+
NSString *const BlockquoteBackgroundColorAttributeName = @"BlockquoteBackgroundColor";
|
|
8
|
+
NSString *const BlockquoteSpacerAttributeName = @"BlockquoteSpacer";
|
|
9
|
+
|
|
10
|
+
@implementation BlockquoteBorder {
|
|
11
|
+
StyleConfig *_config;
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
- (instancetype)initWithConfig:(StyleConfig *)config
|
|
15
|
+
{
|
|
16
|
+
if (self = [super init]) {
|
|
17
|
+
_config = config;
|
|
18
|
+
}
|
|
19
|
+
return self;
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
/**
|
|
23
|
+
* Main drawing entry point called by the LayoutManager.
|
|
24
|
+
* Collects contiguous blockquote regions and draws each as one rounded box:
|
|
25
|
+
* background fill first, then the vertical borders clipped to the box shape.
|
|
26
|
+
* When a border radius is set, each nested quote's stripes are additionally
|
|
27
|
+
* clipped to that quote's own rounded box, mirroring per-element CSS
|
|
28
|
+
* border-radius on web.
|
|
29
|
+
* Regions are discovered by scanning only the drawn character range; regions
|
|
30
|
+
* touching its edges are extended run-by-run to their true boundaries, so the
|
|
31
|
+
* cost scales with the visible text plus the intersecting quotes rather than
|
|
32
|
+
* the whole document.
|
|
33
|
+
*/
|
|
34
|
+
- (void)drawBordersForGlyphRange:(NSRange)glyphsToShow
|
|
35
|
+
layoutManager:(NSLayoutManager *)layoutManager
|
|
36
|
+
textContainer:(NSTextContainer *)textContainer
|
|
37
|
+
atPoint:(CGPoint)origin
|
|
38
|
+
{
|
|
39
|
+
NSTextStorage *textStorage = layoutManager.textStorage;
|
|
40
|
+
if (!textStorage || textStorage.length == 0) {
|
|
41
|
+
return;
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
NSRange charRange = [layoutManager characterRangeForGlyphRange:glyphsToShow actualGlyphRange:NULL];
|
|
45
|
+
if (charRange.location == NSNotFound || charRange.length == 0) {
|
|
46
|
+
return;
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
NSMutableArray<NSValue *> *regions = [NSMutableArray array];
|
|
50
|
+
__block NSRange currentRegion = NSMakeRange(NSNotFound, 0);
|
|
51
|
+
[textStorage enumerateAttribute:BlockquoteDepthAttributeName
|
|
52
|
+
inRange:charRange
|
|
53
|
+
options:0
|
|
54
|
+
usingBlock:^(id value, NSRange range, BOOL *stop) {
|
|
55
|
+
if (!value) {
|
|
56
|
+
if (currentRegion.location != NSNotFound) {
|
|
57
|
+
[regions addObject:[NSValue valueWithRange:currentRegion]];
|
|
58
|
+
currentRegion = NSMakeRange(NSNotFound, 0);
|
|
59
|
+
}
|
|
60
|
+
return;
|
|
61
|
+
}
|
|
62
|
+
currentRegion =
|
|
63
|
+
currentRegion.location == NSNotFound ? range : NSUnionRange(currentRegion, range);
|
|
64
|
+
}];
|
|
65
|
+
if (currentRegion.location != NSNotFound) {
|
|
66
|
+
[regions addObject:[NSValue valueWithRange:currentRegion]];
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
if (regions.count == 0) {
|
|
70
|
+
return;
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
NSRange firstRegion = regions.firstObject.rangeValue;
|
|
74
|
+
if (firstRegion.location == charRange.location) {
|
|
75
|
+
while (firstRegion.location > 0) {
|
|
76
|
+
NSRange runRange;
|
|
77
|
+
if (![textStorage attribute:BlockquoteDepthAttributeName
|
|
78
|
+
atIndex:firstRegion.location - 1
|
|
79
|
+
effectiveRange:&runRange]) {
|
|
80
|
+
break;
|
|
81
|
+
}
|
|
82
|
+
firstRegion = NSUnionRange(firstRegion, runRange);
|
|
83
|
+
}
|
|
84
|
+
regions[0] = [NSValue valueWithRange:firstRegion];
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
NSRange lastRegion = regions.lastObject.rangeValue;
|
|
88
|
+
if (NSMaxRange(lastRegion) == NSMaxRange(charRange)) {
|
|
89
|
+
while (NSMaxRange(lastRegion) < textStorage.length) {
|
|
90
|
+
NSRange runRange;
|
|
91
|
+
if (![textStorage attribute:BlockquoteDepthAttributeName
|
|
92
|
+
atIndex:NSMaxRange(lastRegion)
|
|
93
|
+
effectiveRange:&runRange]) {
|
|
94
|
+
break;
|
|
95
|
+
}
|
|
96
|
+
lastRegion = NSUnionRange(lastRegion, runRange);
|
|
97
|
+
}
|
|
98
|
+
regions[regions.count - 1] = [NSValue valueWithRange:lastRegion];
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
for (NSValue *value in regions) {
|
|
102
|
+
[self drawBlockquoteRegion:value.rangeValue layoutManager:layoutManager textContainer:textContainer atPoint:origin];
|
|
103
|
+
}
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
/**
|
|
107
|
+
* Groups the depth runs of a region into nested quote boxes: for each level
|
|
108
|
+
* >= 1, a box is a maximal contiguous stretch where depth >= level (a nested
|
|
109
|
+
* quote's own range). Outputs parallel arrays of ranges and levels.
|
|
110
|
+
*/
|
|
111
|
+
static void collectNestedBoxes(NSArray<NSValue *> *runRanges, NSArray<NSNumber *> *runDepths,
|
|
112
|
+
NSMutableArray<NSValue *> *boxRanges, NSMutableArray<NSNumber *> *boxLevels)
|
|
113
|
+
{
|
|
114
|
+
NSInteger maxDepth = 0;
|
|
115
|
+
for (NSNumber *depth in runDepths) {
|
|
116
|
+
maxDepth = MAX(maxDepth, depth.integerValue);
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
for (NSInteger level = 1; level <= maxDepth; level++) {
|
|
120
|
+
NSRange current = NSMakeRange(NSNotFound, 0);
|
|
121
|
+
for (NSUInteger i = 0; i < runRanges.count; i++) {
|
|
122
|
+
if (runDepths[i].integerValue >= level) {
|
|
123
|
+
NSRange runRange = runRanges[i].rangeValue;
|
|
124
|
+
current = current.location == NSNotFound ? runRange : NSUnionRange(current, runRange);
|
|
125
|
+
} else if (current.location != NSNotFound) {
|
|
126
|
+
[boxRanges addObject:[NSValue valueWithRange:current]];
|
|
127
|
+
[boxLevels addObject:@(level)];
|
|
128
|
+
current = NSMakeRange(NSNotFound, 0);
|
|
129
|
+
}
|
|
130
|
+
}
|
|
131
|
+
if (current.location != NSNotFound) {
|
|
132
|
+
[boxRanges addObject:[NSValue valueWithRange:current]];
|
|
133
|
+
[boxLevels addObject:@(level)];
|
|
134
|
+
}
|
|
135
|
+
}
|
|
136
|
+
}
|
|
137
|
+
|
|
138
|
+
- (void)drawBlockquoteRegion:(NSRange)region
|
|
139
|
+
layoutManager:(NSLayoutManager *)layoutManager
|
|
140
|
+
textContainer:(NSTextContainer *)textContainer
|
|
141
|
+
atPoint:(CGPoint)origin
|
|
142
|
+
{
|
|
143
|
+
NSTextStorage *textStorage = layoutManager.textStorage;
|
|
144
|
+
|
|
145
|
+
// Cache configuration values to minimize pointer chasing and method lookups in the loop
|
|
146
|
+
StyleConfig *c = _config;
|
|
147
|
+
CGFloat borderWidth = c.blockquoteBorderWidth;
|
|
148
|
+
CGFloat gapWidth = c.blockquoteGapWidth;
|
|
149
|
+
CGFloat levelSpacing = borderWidth + gapWidth;
|
|
150
|
+
CGFloat borderRadius = c.blockquoteBorderRadius;
|
|
151
|
+
CGFloat containerWidth = textContainer.size.width;
|
|
152
|
+
RCTUIColor *defaultBgColor = c.blockquoteBackgroundColor;
|
|
153
|
+
RCTUIColor *borderColor = c.blockquoteBorderColor;
|
|
154
|
+
|
|
155
|
+
NSRange glyphRange = [layoutManager glyphRangeForCharacterRange:region actualCharacterRange:NULL];
|
|
156
|
+
CGRect blockRect = [layoutManager boundingRectForGlyphRange:glyphRange inTextContainer:textContainer];
|
|
157
|
+
if (CGRectIsEmpty(blockRect)) {
|
|
158
|
+
return;
|
|
159
|
+
}
|
|
160
|
+
|
|
161
|
+
blockRect.origin.x = origin.x;
|
|
162
|
+
blockRect.origin.y += origin.y;
|
|
163
|
+
blockRect.size.width = containerWidth;
|
|
164
|
+
|
|
165
|
+
BOOL isLastBlockquote = (NSMaxRange(region) == textStorage.length);
|
|
166
|
+
if (isLastBlockquote) {
|
|
167
|
+
blockRect.size.height += c.blockquotePadding;
|
|
168
|
+
}
|
|
169
|
+
|
|
170
|
+
NSMutableArray<NSValue *> *boxRanges = [NSMutableArray array];
|
|
171
|
+
NSMutableArray<NSNumber *> *boxLevels = [NSMutableArray array];
|
|
172
|
+
NSMutableArray<UIBezierPath *> *boxStripePaths = [NSMutableArray array];
|
|
173
|
+
if (borderRadius > 0) {
|
|
174
|
+
NSMutableArray<NSValue *> *runRanges = [NSMutableArray array];
|
|
175
|
+
NSMutableArray<NSNumber *> *runDepths = [NSMutableArray array];
|
|
176
|
+
[textStorage enumerateAttribute:BlockquoteDepthAttributeName
|
|
177
|
+
inRange:region
|
|
178
|
+
options:0
|
|
179
|
+
usingBlock:^(id value, NSRange range, BOOL *stop) {
|
|
180
|
+
if (!value) {
|
|
181
|
+
return;
|
|
182
|
+
}
|
|
183
|
+
[runRanges addObject:[NSValue valueWithRange:range]];
|
|
184
|
+
[runDepths addObject:value];
|
|
185
|
+
}];
|
|
186
|
+
collectNestedBoxes(runRanges, runDepths, boxRanges, boxLevels);
|
|
187
|
+
for (NSUInteger i = 0; i < boxRanges.count; i++) {
|
|
188
|
+
[boxStripePaths addObject:[UIBezierPath bezierPath]];
|
|
189
|
+
}
|
|
190
|
+
}
|
|
191
|
+
|
|
192
|
+
CGContextRef ctx = UIGraphicsGetCurrentContext();
|
|
193
|
+
CGContextSaveGState(ctx);
|
|
194
|
+
{
|
|
195
|
+
UIBezierPath *boxPath = UIBezierPathWithRoundedRect(blockRect, MAX(0, borderRadius));
|
|
196
|
+
[boxPath addClip];
|
|
197
|
+
|
|
198
|
+
// 1. Draw Background (Painter's algorithm: draw backgrounds before borders)
|
|
199
|
+
RCTUIColor *bgColor = [textStorage attribute:BlockquoteBackgroundColorAttributeName
|
|
200
|
+
atIndex:region.location
|
|
201
|
+
effectiveRange:NULL]
|
|
202
|
+
?: defaultBgColor;
|
|
203
|
+
if (bgColor && bgColor != [RCTUIColor clearColor]) {
|
|
204
|
+
[bgColor setFill];
|
|
205
|
+
CGContextFillRect(ctx, blockRect);
|
|
206
|
+
}
|
|
207
|
+
|
|
208
|
+
// 2. Aggregate vertical borders into batch paths; level-0 stripes are
|
|
209
|
+
// rounded by the region clip, nested stripes by their own box clip below
|
|
210
|
+
UIBezierPath *borderPath = [UIBezierPath bezierPath];
|
|
211
|
+
[layoutManager
|
|
212
|
+
enumerateLineFragmentsForGlyphRange:glyphRange
|
|
213
|
+
usingBlock:^(CGRect rect, CGRect usedRect, NSTextContainer *container,
|
|
214
|
+
NSRange lineGlyphRange, BOOL *stop) {
|
|
215
|
+
NSRange lineCharRange = [layoutManager characterRangeForGlyphRange:lineGlyphRange
|
|
216
|
+
actualGlyphRange:NULL];
|
|
217
|
+
if (lineCharRange.location == NSNotFound || lineCharRange.length == 0) {
|
|
218
|
+
return;
|
|
219
|
+
}
|
|
220
|
+
|
|
221
|
+
NSDictionary *attrs = [textStorage attributesAtIndex:lineCharRange.location
|
|
222
|
+
effectiveRange:NULL];
|
|
223
|
+
NSNumber *depthNum = attrs[BlockquoteDepthAttributeName];
|
|
224
|
+
|
|
225
|
+
if (!depthNum) {
|
|
226
|
+
return;
|
|
227
|
+
}
|
|
228
|
+
|
|
229
|
+
NSInteger depth = [depthNum integerValue];
|
|
230
|
+
CGFloat baseY = origin.y + rect.origin.y;
|
|
231
|
+
CGFloat lineHeight = rect.size.height;
|
|
232
|
+
BOOL isLastLine = NSMaxRange(lineGlyphRange) == NSMaxRange(glyphRange);
|
|
233
|
+
if (isLastBlockquote && isLastLine) {
|
|
234
|
+
lineHeight += c.blockquotePadding;
|
|
235
|
+
}
|
|
236
|
+
BOOL isRTL = ENRMParagraphIsRTL(attrs[NSParagraphStyleAttributeName]);
|
|
237
|
+
|
|
238
|
+
for (NSInteger level = 0; level <= depth; level++) {
|
|
239
|
+
CGFloat borderX =
|
|
240
|
+
isRTL ? origin.x + containerWidth - borderWidth - (levelSpacing * level)
|
|
241
|
+
: origin.x + (levelSpacing * level);
|
|
242
|
+
CGRect borderRect = CGRectMake(borderX, baseY, borderWidth, lineHeight);
|
|
243
|
+
|
|
244
|
+
UIBezierPath *target = borderPath;
|
|
245
|
+
for (NSUInteger b = 0; b < boxRanges.count; b++) {
|
|
246
|
+
if (boxLevels[b].integerValue == level &&
|
|
247
|
+
NSLocationInRange(lineCharRange.location, boxRanges[b].rangeValue)) {
|
|
248
|
+
target = boxStripePaths[b];
|
|
249
|
+
break;
|
|
250
|
+
}
|
|
251
|
+
}
|
|
252
|
+
UIBezierPathAppendPath(target, [UIBezierPath bezierPathWithRect:borderRect]);
|
|
253
|
+
}
|
|
254
|
+
}];
|
|
255
|
+
|
|
256
|
+
// 3. Perform a single batch fill for the root-level borders
|
|
257
|
+
if (!borderPath.isEmpty) {
|
|
258
|
+
[borderColor setFill];
|
|
259
|
+
[borderPath fill];
|
|
260
|
+
}
|
|
261
|
+
|
|
262
|
+
// 4. Nested stripes: clip each to its own quote's rounded box (the clips
|
|
263
|
+
// compose with the still-active region clip)
|
|
264
|
+
for (NSUInteger b = 0; b < boxRanges.count; b++) {
|
|
265
|
+
UIBezierPath *stripes = boxStripePaths[b];
|
|
266
|
+
if (stripes.isEmpty) {
|
|
267
|
+
continue;
|
|
268
|
+
}
|
|
269
|
+
|
|
270
|
+
NSRange boxRange = boxRanges[b].rangeValue;
|
|
271
|
+
NSRange boxGlyphRange = [layoutManager glyphRangeForCharacterRange:boxRange actualCharacterRange:NULL];
|
|
272
|
+
CGRect boxRect = [layoutManager boundingRectForGlyphRange:boxGlyphRange inTextContainer:textContainer];
|
|
273
|
+
if (CGRectIsEmpty(boxRect)) {
|
|
274
|
+
continue;
|
|
275
|
+
}
|
|
276
|
+
|
|
277
|
+
NSDictionary *boxAttrs = [textStorage attributesAtIndex:boxRange.location effectiveRange:NULL];
|
|
278
|
+
BOOL boxRTL = ENRMParagraphIsRTL(boxAttrs[NSParagraphStyleAttributeName]);
|
|
279
|
+
CGFloat leadingInset = levelSpacing * boxLevels[b].integerValue;
|
|
280
|
+
boxRect.origin.x = boxRTL ? origin.x : origin.x + leadingInset;
|
|
281
|
+
boxRect.origin.y += origin.y;
|
|
282
|
+
boxRect.size.width = containerWidth - leadingInset;
|
|
283
|
+
|
|
284
|
+
CGContextSaveGState(ctx);
|
|
285
|
+
[UIBezierPathWithRoundedRect(boxRect, borderRadius) addClip];
|
|
286
|
+
[borderColor setFill];
|
|
287
|
+
[stripes fill];
|
|
288
|
+
CGContextRestoreGState(ctx);
|
|
289
|
+
}
|
|
290
|
+
}
|
|
291
|
+
CGContextRestoreGState(ctx);
|
|
292
|
+
}
|
|
293
|
+
|
|
294
|
+
@end
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
#pragma once
|
|
2
|
+
#import "ENRMUIKit.h"
|
|
3
|
+
#import "StyleConfig.h"
|
|
4
|
+
|
|
5
|
+
NS_ASSUME_NONNULL_BEGIN
|
|
6
|
+
|
|
7
|
+
extern NSString *const CodeAttributeName;
|
|
8
|
+
|
|
9
|
+
@interface CodeBackground : NSObject
|
|
10
|
+
|
|
11
|
+
- (instancetype)initWithConfig:(StyleConfig *)config;
|
|
12
|
+
- (void)drawBackgroundsForGlyphRange:(NSRange)glyphsToShow
|
|
13
|
+
layoutManager:(NSLayoutManager *)layoutManager
|
|
14
|
+
textContainer:(NSTextContainer *)textContainer
|
|
15
|
+
atPoint:(CGPoint)origin;
|
|
16
|
+
|
|
17
|
+
@end
|
|
18
|
+
|
|
19
|
+
NS_ASSUME_NONNULL_END
|
|
@@ -0,0 +1,197 @@
|
|
|
1
|
+
#import "CodeBackground.h"
|
|
2
|
+
#import "ENRMUIKit.h"
|
|
3
|
+
#import "RenderContext.h"
|
|
4
|
+
|
|
5
|
+
NSString *const CodeAttributeName = @"Code";
|
|
6
|
+
|
|
7
|
+
static const CGFloat kCodeBackgroundCornerRadius = 2.0;
|
|
8
|
+
static const CGFloat kCodeBackgroundBorderWidth = 0.5;
|
|
9
|
+
|
|
10
|
+
@implementation CodeBackground {
|
|
11
|
+
StyleConfig *_config;
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
- (instancetype)initWithConfig:(StyleConfig *)config
|
|
15
|
+
{
|
|
16
|
+
self = [super init];
|
|
17
|
+
if (self) {
|
|
18
|
+
_config = config;
|
|
19
|
+
}
|
|
20
|
+
return self;
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
- (void)drawBackgroundsForGlyphRange:(NSRange)glyphsToShow
|
|
24
|
+
layoutManager:(NSLayoutManager *)layoutManager
|
|
25
|
+
textContainer:(NSTextContainer *)textContainer
|
|
26
|
+
atPoint:(CGPoint)origin
|
|
27
|
+
{
|
|
28
|
+
RCTUIColor *backgroundColor = _config.codeBackgroundColor;
|
|
29
|
+
if (!backgroundColor)
|
|
30
|
+
return;
|
|
31
|
+
|
|
32
|
+
NSTextStorage *textStorage = layoutManager.textStorage;
|
|
33
|
+
NSRange charRange = [layoutManager characterRangeForGlyphRange:glyphsToShow actualGlyphRange:NULL];
|
|
34
|
+
if (charRange.location == NSNotFound || charRange.length == 0)
|
|
35
|
+
return;
|
|
36
|
+
|
|
37
|
+
[textStorage enumerateAttribute:CodeAttributeName
|
|
38
|
+
inRange:NSMakeRange(0, textStorage.length)
|
|
39
|
+
options:0
|
|
40
|
+
usingBlock:^(id value, NSRange range, BOOL *stop) {
|
|
41
|
+
if (!value || range.length == 0)
|
|
42
|
+
return;
|
|
43
|
+
if (NSIntersectionRange(range, charRange).length == 0)
|
|
44
|
+
return;
|
|
45
|
+
|
|
46
|
+
[self drawCodeBackgroundForRange:range
|
|
47
|
+
layoutManager:layoutManager
|
|
48
|
+
textContainer:textContainer
|
|
49
|
+
atPoint:origin
|
|
50
|
+
backgroundColor:backgroundColor
|
|
51
|
+
borderColor:self->_config.codeBorderColor];
|
|
52
|
+
}];
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
- (void)drawCodeBackgroundForRange:(NSRange)range
|
|
56
|
+
layoutManager:(NSLayoutManager *)layoutManager
|
|
57
|
+
textContainer:(NSTextContainer *)textContainer
|
|
58
|
+
atPoint:(CGPoint)origin
|
|
59
|
+
backgroundColor:(RCTUIColor *)backgroundColor
|
|
60
|
+
borderColor:(RCTUIColor *)borderColor
|
|
61
|
+
{
|
|
62
|
+
NSRange glyphRange = [layoutManager glyphRangeForCharacterRange:range actualCharacterRange:NULL];
|
|
63
|
+
if (glyphRange.location == NSNotFound || glyphRange.length == 0)
|
|
64
|
+
return;
|
|
65
|
+
|
|
66
|
+
CGFloat referenceHeight = [self findReferenceHeightForRange:range textStorage:layoutManager.textStorage];
|
|
67
|
+
|
|
68
|
+
[layoutManager
|
|
69
|
+
enumerateLineFragmentsForGlyphRange:glyphRange
|
|
70
|
+
usingBlock:^(CGRect rect, CGRect usedRect, NSTextContainer *tc, NSRange lineRange,
|
|
71
|
+
BOOL *stop) {
|
|
72
|
+
NSRange intersect = NSIntersectionRange(lineRange, glyphRange);
|
|
73
|
+
if (intersect.length == 0)
|
|
74
|
+
return;
|
|
75
|
+
|
|
76
|
+
BOOL isFirst = (intersect.location == glyphRange.location);
|
|
77
|
+
BOOL isLast = (NSMaxRange(intersect) == NSMaxRange(glyphRange));
|
|
78
|
+
|
|
79
|
+
CGRect finalRect;
|
|
80
|
+
if (isFirst || isLast) {
|
|
81
|
+
// Precise bounds are only required for the start and end of the span
|
|
82
|
+
CGRect textRect = [layoutManager boundingRectForGlyphRange:intersect
|
|
83
|
+
inTextContainer:textContainer];
|
|
84
|
+
finalRect = CGRectMake(textRect.origin.x + origin.x, textRect.origin.y + origin.y,
|
|
85
|
+
textRect.size.width, textRect.size.height);
|
|
86
|
+
|
|
87
|
+
// For multi-line, extend the first line to the right edge of the fragment
|
|
88
|
+
if (isFirst && !isLast) {
|
|
89
|
+
finalRect.size.width =
|
|
90
|
+
(usedRect.origin.x + usedRect.size.width + origin.x) - finalRect.origin.x;
|
|
91
|
+
}
|
|
92
|
+
} else {
|
|
93
|
+
// OPTIMIZATION: Middle lines use the usedRect of the fragment directly
|
|
94
|
+
finalRect = CGRectMake(usedRect.origin.x + origin.x, usedRect.origin.y + origin.y,
|
|
95
|
+
usedRect.size.width, usedRect.size.height);
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
// Ensure consistent height and no gaps
|
|
99
|
+
if (finalRect.size.height < referenceHeight) {
|
|
100
|
+
finalRect.size.height = referenceHeight;
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
[self drawBackgroundAndBorders:finalRect
|
|
104
|
+
backgroundColor:backgroundColor
|
|
105
|
+
borderColor:borderColor
|
|
106
|
+
isFirst:isFirst
|
|
107
|
+
isLast:isLast];
|
|
108
|
+
}];
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
#pragma mark - Drawing Logic
|
|
112
|
+
|
|
113
|
+
- (void)drawBackgroundAndBorders:(CGRect)rect
|
|
114
|
+
backgroundColor:(RCTUIColor *)backgroundColor
|
|
115
|
+
borderColor:(RCTUIColor *)borderColor
|
|
116
|
+
isFirst:(BOOL)isFirst
|
|
117
|
+
isLast:(BOOL)isLast
|
|
118
|
+
{
|
|
119
|
+
UIBezierPath *path = [self pathForRect:rect isFirst:isFirst isLast:isLast];
|
|
120
|
+
[backgroundColor setFill];
|
|
121
|
+
[path fill];
|
|
122
|
+
|
|
123
|
+
if (borderColor) {
|
|
124
|
+
[borderColor setStroke];
|
|
125
|
+
UIBezierPath *strokePath =
|
|
126
|
+
(isFirst && isLast) ? path : [self openBorderPathForRect:rect isFirst:isFirst isLast:isLast];
|
|
127
|
+
strokePath.lineWidth = kCodeBackgroundBorderWidth;
|
|
128
|
+
BezierPathSetRoundStyle(strokePath);
|
|
129
|
+
[strokePath stroke];
|
|
130
|
+
}
|
|
131
|
+
}
|
|
132
|
+
|
|
133
|
+
- (UIBezierPath *)pathForRect:(CGRect)rect isFirst:(BOOL)isFirst isLast:(BOOL)isLast
|
|
134
|
+
{
|
|
135
|
+
#if !TARGET_OS_OSX
|
|
136
|
+
UIRectCorner corners = 0;
|
|
137
|
+
if (isFirst)
|
|
138
|
+
corners |= (UIRectCornerTopLeft | UIRectCornerBottomLeft);
|
|
139
|
+
if (isLast)
|
|
140
|
+
corners |= (UIRectCornerTopRight | UIRectCornerBottomRight);
|
|
141
|
+
|
|
142
|
+
return [UIBezierPath bezierPathWithRoundedRect:rect
|
|
143
|
+
byRoundingCorners:corners
|
|
144
|
+
cornerRadii:CGSizeMake(kCodeBackgroundCornerRadius, kCodeBackgroundCornerRadius)];
|
|
145
|
+
#else
|
|
146
|
+
// NSBezierPath doesn't support per-corner rounding — use uniform corner radius
|
|
147
|
+
CGFloat cornerRadius = (isFirst || isLast) ? kCodeBackgroundCornerRadius : 0;
|
|
148
|
+
return UIBezierPathWithRoundedRect(rect, cornerRadius);
|
|
149
|
+
#endif
|
|
150
|
+
}
|
|
151
|
+
|
|
152
|
+
- (UIBezierPath *)openBorderPathForRect:(CGRect)rect isFirst:(BOOL)isFirst isLast:(BOOL)isLast
|
|
153
|
+
{
|
|
154
|
+
UIBezierPath *path = [UIBezierPath bezierPath];
|
|
155
|
+
CGFloat r = kCodeBackgroundCornerRadius;
|
|
156
|
+
CGFloat inset = kCodeBackgroundBorderWidth / 2.0;
|
|
157
|
+
CGRect insetRect = CGRectInset(rect, inset, inset);
|
|
158
|
+
|
|
159
|
+
if (isFirst) {
|
|
160
|
+
[path moveToPoint:CGPointMake(CGRectGetMaxX(rect), insetRect.origin.y)];
|
|
161
|
+
BezierPathAddLine(path, CGPointMake(insetRect.origin.x + r, insetRect.origin.y));
|
|
162
|
+
BezierPathAddQuadCurve(path, CGPointMake(insetRect.origin.x, insetRect.origin.y + r),
|
|
163
|
+
CGPointMake(insetRect.origin.x, insetRect.origin.y));
|
|
164
|
+
BezierPathAddLine(path, CGPointMake(insetRect.origin.x, CGRectGetMaxY(insetRect) - r));
|
|
165
|
+
BezierPathAddQuadCurve(path, CGPointMake(insetRect.origin.x + r, CGRectGetMaxY(insetRect)),
|
|
166
|
+
CGPointMake(insetRect.origin.x, CGRectGetMaxY(insetRect)));
|
|
167
|
+
BezierPathAddLine(path, CGPointMake(CGRectGetMaxX(rect), CGRectGetMaxY(insetRect)));
|
|
168
|
+
} else if (isLast) {
|
|
169
|
+
[path moveToPoint:CGPointMake(rect.origin.x, insetRect.origin.y)];
|
|
170
|
+
BezierPathAddLine(path, CGPointMake(CGRectGetMaxX(insetRect) - r, insetRect.origin.y));
|
|
171
|
+
BezierPathAddQuadCurve(path, CGPointMake(CGRectGetMaxX(insetRect), insetRect.origin.y + r),
|
|
172
|
+
CGPointMake(CGRectGetMaxX(insetRect), insetRect.origin.y));
|
|
173
|
+
BezierPathAddLine(path, CGPointMake(CGRectGetMaxX(insetRect), CGRectGetMaxY(insetRect) - r));
|
|
174
|
+
BezierPathAddQuadCurve(path, CGPointMake(CGRectGetMaxX(insetRect) - r, CGRectGetMaxY(insetRect)),
|
|
175
|
+
CGPointMake(CGRectGetMaxX(insetRect), CGRectGetMaxY(insetRect)));
|
|
176
|
+
BezierPathAddLine(path, CGPointMake(rect.origin.x, CGRectGetMaxY(insetRect)));
|
|
177
|
+
} else {
|
|
178
|
+
[path moveToPoint:CGPointMake(rect.origin.x, insetRect.origin.y)];
|
|
179
|
+
BezierPathAddLine(path, CGPointMake(CGRectGetMaxX(rect), insetRect.origin.y));
|
|
180
|
+
[path moveToPoint:CGPointMake(rect.origin.x, CGRectGetMaxY(insetRect))];
|
|
181
|
+
BezierPathAddLine(path, CGPointMake(CGRectGetMaxX(rect), CGRectGetMaxY(insetRect)));
|
|
182
|
+
}
|
|
183
|
+
return path;
|
|
184
|
+
}
|
|
185
|
+
|
|
186
|
+
#pragma mark - Helpers
|
|
187
|
+
|
|
188
|
+
- (CGFloat)findReferenceHeightForRange:(NSRange)range textStorage:(NSTextStorage *)textStorage
|
|
189
|
+
{
|
|
190
|
+
if (range.location == NSNotFound || range.length == 0 || !textStorage) {
|
|
191
|
+
return [_config paragraphFontSize] * 1.2;
|
|
192
|
+
}
|
|
193
|
+
NSNumber *lineHeightValue = [textStorage attribute:@"BlockLineHeight" atIndex:range.location effectiveRange:NULL];
|
|
194
|
+
return lineHeightValue ? [lineHeightValue doubleValue] : ([_config paragraphFontSize] * 1.2);
|
|
195
|
+
}
|
|
196
|
+
|
|
197
|
+
@end
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
#pragma once
|
|
2
|
+
#import "ENRMUIKit.h"
|
|
3
|
+
#import "StyleConfig.h"
|
|
4
|
+
|
|
5
|
+
NS_ASSUME_NONNULL_BEGIN
|
|
6
|
+
|
|
7
|
+
@interface CodeBlockBackground : NSObject
|
|
8
|
+
|
|
9
|
+
- (instancetype)initWithConfig:(StyleConfig *)config;
|
|
10
|
+
- (void)drawBackgroundsForGlyphRange:(NSRange)glyphsToShow
|
|
11
|
+
layoutManager:(NSLayoutManager *)layoutManager
|
|
12
|
+
textContainer:(NSTextContainer *)textContainer
|
|
13
|
+
atPoint:(CGPoint)origin;
|
|
14
|
+
|
|
15
|
+
@end
|
|
16
|
+
|
|
17
|
+
NS_ASSUME_NONNULL_END
|