@mathers101/react-native-render-rich-text 0.1.10 → 0.1.14
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +20 -20
- package/README.md +140 -140
- package/ReactNativeRenderRichText.podspec +23 -23
- package/android/build.gradle +86 -86
- package/android/consumer-rules.pro +3 -3
- package/android/src/main/AndroidManifest.xml +2 -2
- package/android/src/main/java/com/renderrichtext/EnrichedTiptapTextLayoutManager.kt +24 -24
- package/android/src/main/java/com/renderrichtext/EnrichedTiptapTextPackage.kt +13 -13
- package/android/src/main/java/com/renderrichtext/MeasurementStore.kt +644 -644
- package/android/src/main/java/com/renderrichtext/accessibility/AccessibilityLabels.kt +17 -17
- package/android/src/main/java/com/renderrichtext/accessibility/AccessibleTiptapTextView.kt +112 -112
- package/android/src/main/java/com/renderrichtext/accessibility/TiptapAccessibilityHelper.kt +576 -576
- package/android/src/main/java/com/renderrichtext/events/CodeBlockPressEvent.kt +24 -24
- package/android/src/main/java/com/renderrichtext/events/ContextMenuItemPressEvent.kt +28 -28
- package/android/src/main/java/com/renderrichtext/events/CopyPressEvent.kt +24 -24
- package/android/src/main/java/com/renderrichtext/events/ImagePressEvent.kt +25 -25
- package/android/src/main/java/com/renderrichtext/events/LatexErrorEvent.kt +29 -29
- package/android/src/main/java/com/renderrichtext/events/LinkLongPressEvent.kt +23 -23
- package/android/src/main/java/com/renderrichtext/events/LinkPressEvent.kt +23 -23
- package/android/src/main/java/com/renderrichtext/events/MentionLongPressEvent.kt +25 -25
- package/android/src/main/java/com/renderrichtext/events/MentionPressEvent.kt +25 -25
- package/android/src/main/java/com/renderrichtext/events/TaskListItemPressEvent.kt +26 -26
- package/android/src/main/java/com/renderrichtext/math/LatexErrorReporter.kt +9 -9
- package/android/src/main/java/com/renderrichtext/parser/Parser.kt +59 -59
- package/android/src/main/java/com/renderrichtext/parser/TextLinkMatching.kt +35 -35
- package/android/src/main/java/com/renderrichtext/renderer/BaselineShiftRenderer.kt +45 -45
- package/android/src/main/java/com/renderrichtext/renderer/BlankLineRenderer.kt +39 -39
- package/android/src/main/java/com/renderrichtext/renderer/BlockquoteRenderer.kt +243 -243
- package/android/src/main/java/com/renderrichtext/renderer/BlockquoteTextRenderer.kt +56 -56
- package/android/src/main/java/com/renderrichtext/renderer/CodeBlockRenderer.kt +135 -135
- package/android/src/main/java/com/renderrichtext/renderer/CodeRenderer.kt +37 -37
- package/android/src/main/java/com/renderrichtext/renderer/EmphasisRenderer.kt +28 -28
- package/android/src/main/java/com/renderrichtext/renderer/HeadingRenderer.kt +81 -81
- package/android/src/main/java/com/renderrichtext/renderer/HighlightRenderer.kt +26 -26
- package/android/src/main/java/com/renderrichtext/renderer/LineBreakRenderer.kt +17 -17
- package/android/src/main/java/com/renderrichtext/renderer/LinkRenderer.kt +90 -90
- package/android/src/main/java/com/renderrichtext/renderer/ListContextManager.kt +109 -109
- package/android/src/main/java/com/renderrichtext/renderer/ListItemRenderer.kt +211 -211
- package/android/src/main/java/com/renderrichtext/renderer/ListRenderer.kt +133 -133
- package/android/src/main/java/com/renderrichtext/renderer/MentionRenderer.kt +85 -85
- package/android/src/main/java/com/renderrichtext/renderer/ParagraphRenderer.kt +91 -91
- package/android/src/main/java/com/renderrichtext/renderer/Renderer.kt +148 -148
- package/android/src/main/java/com/renderrichtext/renderer/SoftBreakRenderer.kt +17 -17
- package/android/src/main/java/com/renderrichtext/renderer/SpanStyleCache.kt +143 -143
- package/android/src/main/java/com/renderrichtext/renderer/StrikethroughRenderer.kt +28 -28
- package/android/src/main/java/com/renderrichtext/renderer/StrongRenderer.kt +28 -28
- package/android/src/main/java/com/renderrichtext/renderer/TextRenderer.kt +31 -31
- package/android/src/main/java/com/renderrichtext/renderer/ThematicBreakRenderer.kt +46 -46
- package/android/src/main/java/com/renderrichtext/renderer/UnderlineRenderer.kt +28 -28
- package/android/src/main/java/com/renderrichtext/spans/BaseListSpan.kt +164 -164
- package/android/src/main/java/com/renderrichtext/spans/BaselineShiftSpan.kt +27 -27
- package/android/src/main/java/com/renderrichtext/spans/BlockquoteSpan.kt +302 -302
- package/android/src/main/java/com/renderrichtext/spans/CodeBackgroundSpan.kt +205 -205
- package/android/src/main/java/com/renderrichtext/spans/CodeBlockSpan.kt +216 -216
- package/android/src/main/java/com/renderrichtext/spans/CodeSpan.kt +32 -32
- package/android/src/main/java/com/renderrichtext/spans/EmphasisSpan.kt +42 -42
- package/android/src/main/java/com/renderrichtext/spans/FadeInSpan.kt +29 -29
- package/android/src/main/java/com/renderrichtext/spans/HeadingSpan.kt +38 -38
- package/android/src/main/java/com/renderrichtext/spans/HighlightSpan.kt +80 -80
- package/android/src/main/java/com/renderrichtext/spans/ImageSpan.kt +481 -481
- package/android/src/main/java/com/renderrichtext/spans/InlineBackgroundGeometry.kt +42 -42
- package/android/src/main/java/com/renderrichtext/spans/LineHeightSpan.kt +39 -39
- package/android/src/main/java/com/renderrichtext/spans/LinkPillIconCache.kt +154 -154
- package/android/src/main/java/com/renderrichtext/spans/LinkPillSpan.kt +381 -381
- package/android/src/main/java/com/renderrichtext/spans/LinkSpan.kt +68 -68
- package/android/src/main/java/com/renderrichtext/spans/ListItemSpacingSpan.kt +33 -33
- package/android/src/main/java/com/renderrichtext/spans/ListMarkerAnchorSpan.kt +38 -38
- package/android/src/main/java/com/renderrichtext/spans/MarginBottomSpan.kt +76 -76
- package/android/src/main/java/com/renderrichtext/spans/MentionChipSpan.kt +132 -132
- package/android/src/main/java/com/renderrichtext/spans/MentionSpan.kt +46 -46
- package/android/src/main/java/com/renderrichtext/spans/OrderedListSpan.kt +127 -127
- package/android/src/main/java/com/renderrichtext/spans/SpoilerSpan.kt +33 -33
- package/android/src/main/java/com/renderrichtext/spans/StrikethroughSpan.kt +12 -12
- package/android/src/main/java/com/renderrichtext/spans/StrongSpan.kt +39 -39
- package/android/src/main/java/com/renderrichtext/spans/TaskListSpan.kt +143 -143
- package/android/src/main/java/com/renderrichtext/spans/TextSpan.kt +26 -26
- package/android/src/main/java/com/renderrichtext/spans/ThematicBreakSpan.kt +69 -69
- package/android/src/main/java/com/renderrichtext/spans/UnorderedListSpan.kt +96 -96
- package/android/src/main/java/com/renderrichtext/spoiler/SpoilerStubs.kt +46 -46
- package/android/src/main/java/com/renderrichtext/styles/BaseBlockStyle.kt +11 -11
- package/android/src/main/java/com/renderrichtext/styles/BlockquoteStyle.kt +83 -83
- package/android/src/main/java/com/renderrichtext/styles/CodeBlockStyle.kt +80 -80
- package/android/src/main/java/com/renderrichtext/styles/CodeStyle.kt +26 -26
- package/android/src/main/java/com/renderrichtext/styles/EmphasisStyle.kt +21 -21
- package/android/src/main/java/com/renderrichtext/styles/FactoidStyle.kt +21 -21
- package/android/src/main/java/com/renderrichtext/styles/HeadingStyle.kt +33 -33
- package/android/src/main/java/com/renderrichtext/styles/HighlightStyle.kt +19 -19
- package/android/src/main/java/com/renderrichtext/styles/ImageStyle.kt +29 -29
- package/android/src/main/java/com/renderrichtext/styles/InlineImageStyle.kt +17 -17
- package/android/src/main/java/com/renderrichtext/styles/InlineMathStyle.kt +17 -17
- package/android/src/main/java/com/renderrichtext/styles/LinkPillContent.kt +36 -36
- package/android/src/main/java/com/renderrichtext/styles/LinkPillStyle.kt +44 -44
- package/android/src/main/java/com/renderrichtext/styles/LinkStyle.kt +23 -23
- package/android/src/main/java/com/renderrichtext/styles/LinkVariantEntry.kt +34 -34
- package/android/src/main/java/com/renderrichtext/styles/ListStyle.kt +65 -65
- package/android/src/main/java/com/renderrichtext/styles/MathStyle.kt +29 -29
- package/android/src/main/java/com/renderrichtext/styles/MentionStyle.kt +19 -19
- package/android/src/main/java/com/renderrichtext/styles/ParagraphStyle.kt +33 -33
- package/android/src/main/java/com/renderrichtext/styles/SpoilerStyle.kt +27 -27
- package/android/src/main/java/com/renderrichtext/styles/StrikethroughStyle.kt +17 -17
- package/android/src/main/java/com/renderrichtext/styles/StrongStyle.kt +21 -21
- package/android/src/main/java/com/renderrichtext/styles/StyleConfig.kt +411 -411
- package/android/src/main/java/com/renderrichtext/styles/StyleParser.kt +92 -92
- package/android/src/main/java/com/renderrichtext/styles/SubscriptStyle.kt +16 -16
- package/android/src/main/java/com/renderrichtext/styles/SuperscriptStyle.kt +16 -16
- package/android/src/main/java/com/renderrichtext/styles/TableStyle.kt +75 -75
- package/android/src/main/java/com/renderrichtext/styles/TaskListStyle.kt +29 -29
- package/android/src/main/java/com/renderrichtext/styles/TextAlignment.kt +32 -32
- package/android/src/main/java/com/renderrichtext/styles/ThematicBreakStyle.kt +23 -23
- package/android/src/main/java/com/renderrichtext/styles/UnderlineStyle.kt +17 -17
- package/android/src/main/java/com/renderrichtext/styles/VideoStyle.kt +31 -31
- package/android/src/main/java/com/renderrichtext/utils/common/BorderStyleUtils.kt +86 -86
- package/android/src/main/java/com/renderrichtext/utils/common/BreakStrategyUtils.kt +32 -32
- package/android/src/main/java/com/renderrichtext/utils/common/CodeBlockHighlighter.kt +36 -36
- package/android/src/main/java/com/renderrichtext/utils/common/CodeBlockNode.kt +42 -42
- package/android/src/main/java/com/renderrichtext/utils/common/EllipsizeUtils.kt +27 -27
- package/android/src/main/java/com/renderrichtext/utils/common/EnrichedTiptapAncestorUtils.kt +10 -10
- package/android/src/main/java/com/renderrichtext/utils/common/FeatureFlags.kt +9 -9
- package/android/src/main/java/com/renderrichtext/utils/common/LinkRecognitionProps.kt +31 -31
- package/android/src/main/java/com/renderrichtext/utils/common/LinkRegexConfig.kt +56 -56
- package/android/src/main/java/com/renderrichtext/utils/common/MotionPreferences.kt +18 -18
- package/android/src/main/java/com/renderrichtext/utils/common/ReadableMapExtensions.kt +28 -28
- package/android/src/main/java/com/renderrichtext/utils/common/layout/RTLUtils.kt +6 -6
- package/android/src/main/java/com/renderrichtext/utils/common/serialization/TiptapASTSerializer.kt +368 -368
- package/android/src/main/java/com/renderrichtext/utils/text/ImageCache.kt +88 -88
- package/android/src/main/java/com/renderrichtext/utils/text/ImageDownloader.kt +203 -203
- package/android/src/main/java/com/renderrichtext/utils/text/LocalImageLoader.kt +167 -167
- package/android/src/main/java/com/renderrichtext/utils/text/TailFadeInAnimator.kt +84 -84
- package/android/src/main/java/com/renderrichtext/utils/text/conversion/HTMLGenerator.kt +1105 -1105
- package/android/src/main/java/com/renderrichtext/utils/text/conversion/TiptapExtractor.kt +423 -423
- package/android/src/main/java/com/renderrichtext/utils/text/extensions/ParagraphUtils.kt +9 -9
- package/android/src/main/java/com/renderrichtext/utils/text/extensions/SpannableExtensions.kt +9 -9
- package/android/src/main/java/com/renderrichtext/utils/text/extensions/TextPaintExtensions.kt +76 -76
- package/android/src/main/java/com/renderrichtext/utils/text/interaction/CheckboxTouchHelper.kt +61 -61
- package/android/src/main/java/com/renderrichtext/utils/text/interaction/TaskListTapUtils.kt +286 -286
- package/android/src/main/java/com/renderrichtext/utils/text/span/ApplyLineHeight.kt +39 -39
- package/android/src/main/java/com/renderrichtext/utils/text/span/BlockSpacing.kt +142 -142
- package/android/src/main/java/com/renderrichtext/utils/text/span/SpanFlags.kt +43 -43
- package/android/src/main/java/com/renderrichtext/utils/text/span/WidthAwareSpans.kt +30 -30
- package/android/src/main/java/com/renderrichtext/utils/text/view/CodeBlockPressHost.kt +15 -15
- package/android/src/main/java/com/renderrichtext/utils/text/view/ImagePressHost.kt +19 -19
- package/android/src/main/java/com/renderrichtext/utils/text/view/SelectionActionMode.kt +235 -235
- package/android/src/main/java/com/renderrichtext/utils/text/view/TextSelectionColors.kt +48 -48
- package/android/src/main/java/com/renderrichtext/utils/text/view/TextViewSetup.kt +119 -119
- package/android/src/main/java/com/renderrichtext/views/ContextMenuPopup.kt +217 -217
- package/android/src/main/java/com/renderrichtext/views/CopyGlyph.kt +101 -101
- package/android/src/main/java/com/renderrichtext/views/WrapGlyph.kt +40 -40
- package/android/src/main/jni/CMakeLists.txt +52 -52
- package/android/src/main/jni/react/renderer/components/RichTextSpec/ComponentDescriptors.h +30 -30
- package/android/src/main/jni/react/renderer/components/RichTextSpec/TiptapTextComponentDescriptor.h +29 -29
- package/android/src/main/jni/react/renderer/components/RichTextSpec/TiptapTextMeasurementManager.cpp +45 -45
- package/android/src/main/jni/react/renderer/components/RichTextSpec/TiptapTextMeasurementManager.h +21 -21
- package/android/src/main/jni/react/renderer/components/RichTextSpec/TiptapTextShadowNode.cpp +38 -38
- package/android/src/main/jni/react/renderer/components/RichTextSpec/TiptapTextShadowNode.h +53 -53
- package/android/src/main/jni/react/renderer/components/RichTextSpec/TiptapTextState.cpp +9 -9
- package/android/src/main/jni/react/renderer/components/RichTextSpec/TiptapTextState.h +24 -24
- package/android/src/main/jni/react/renderer/components/RichTextSpec/conversions.h +40 -40
- package/cpp/parser/TiptapParser.hpp +13 -13
- package/cpp/vendor/nlohmann/json.hpp +24765 -24765
- package/ios/EnrichedTiptapText.h +27 -27
- package/ios/attachments/ENRMImageAttachment.h +51 -51
- package/ios/attachments/ENRMImageAttachment.m +398 -398
- package/ios/attachments/ENRMLinkPillAttachment.h +47 -47
- package/ios/attachments/ENRMLinkPillAttachment.m +324 -324
- package/ios/attachments/ENRMLinkPillIconCache.h +28 -28
- package/ios/attachments/ENRMLinkPillIconCache.m +181 -181
- package/ios/attachments/ENRMLinkPillText.h +27 -27
- package/ios/attachments/ENRMLinkPillText.m +118 -118
- package/ios/attachments/ENRMMathInlineAttachment.h +7 -7
- package/ios/attachments/ENRMMathInlineAttachment.m +4 -4
- package/ios/attachments/ThematicBreakAttachment.h +15 -15
- package/ios/attachments/ThematicBreakAttachment.m +33 -33
- package/ios/internals/ENRMViewFreeMeasurement.h +208 -208
- package/ios/internals/EnrichedTiptapTextComponentDescriptor.h +19 -19
- package/ios/internals/EnrichedTiptapTextShadowNode.h +43 -43
- package/ios/internals/EnrichedTiptapTextShadowNode.mm +69 -69
- package/ios/internals/EnrichedTiptapTextState.h +24 -24
- package/ios/internals/MeasurementCache.h +308 -308
- package/ios/internals/ShadowMeasurementUtils.h +145 -145
- package/ios/parser/ENRMTextLinkAttributes.h +7 -7
- package/ios/parser/ENRMTiptapParser.h +33 -33
- package/ios/parser/ENRMTiptapParser.mm +73 -73
- package/ios/parser/TiptapASTNode.m +52 -52
- package/ios/renderer/AttributedRenderer.h +23 -23
- package/ios/renderer/AttributedRenderer.m +229 -229
- package/ios/renderer/BaseRenderer.h +33 -33
- package/ios/renderer/BaseRenderer.m +46 -46
- package/ios/renderer/BaselineShiftTextAttributes.h +10 -10
- package/ios/renderer/BaselineShiftTextAttributes.m +26 -26
- package/ios/renderer/BlankLineRenderer.h +4 -4
- package/ios/renderer/BlankLineRenderer.m +51 -51
- package/ios/renderer/BlockquoteRenderer.h +6 -6
- package/ios/renderer/BlockquoteRenderer.m +258 -258
- package/ios/renderer/CodeBlockRenderer.h +9 -9
- package/ios/renderer/CodeBlockRenderer.m +99 -99
- package/ios/renderer/CodeRenderer.h +9 -9
- package/ios/renderer/CodeRenderer.m +69 -69
- package/ios/renderer/ENRMBlockquoteTextRenderer.h +25 -25
- package/ios/renderer/ENRMBlockquoteTextRenderer.m +48 -48
- package/ios/renderer/EmphasisRenderer.h +5 -5
- package/ios/renderer/EmphasisRenderer.m +99 -99
- package/ios/renderer/HeadingRenderer.h +6 -6
- package/ios/renderer/HeadingRenderer.m +102 -102
- package/ios/renderer/HighlightRenderer.h +7 -7
- package/ios/renderer/HighlightRenderer.m +33 -33
- package/ios/renderer/LinkRenderer.h +6 -6
- package/ios/renderer/LinkRenderer.m +157 -157
- package/ios/renderer/ListItemRenderer.h +24 -24
- package/ios/renderer/ListItemRenderer.m +283 -283
- package/ios/renderer/ListRenderer.h +13 -13
- package/ios/renderer/ListRenderer.m +126 -126
- package/ios/renderer/MentionRenderer.h +9 -9
- package/ios/renderer/MentionRenderer.m +96 -96
- package/ios/renderer/NodeRenderer.h +8 -8
- package/ios/renderer/ParagraphRenderer.h +6 -6
- package/ios/renderer/ParagraphRenderer.m +85 -85
- package/ios/renderer/RenderContext.h +145 -145
- package/ios/renderer/RenderContext.m +402 -402
- package/ios/renderer/RendererFactory.h +12 -12
- package/ios/renderer/StrikethroughRenderer.h +5 -5
- package/ios/renderer/StrikethroughRenderer.m +30 -30
- package/ios/renderer/StrongRenderer.h +5 -5
- package/ios/renderer/StrongRenderer.m +87 -87
- package/ios/renderer/TextRenderer.h +6 -6
- package/ios/renderer/TextRenderer.m +18 -18
- package/ios/renderer/ThematicBreakRenderer.h +4 -4
- package/ios/renderer/ThematicBreakRenderer.m +41 -41
- package/ios/renderer/UnderlineRenderer.h +4 -4
- package/ios/renderer/UnderlineRenderer.m +41 -41
- package/ios/styles/ENRMFontSlot.h +12 -12
- package/ios/styles/ENRMFontSlot.m +24 -24
- package/ios/styles/StyleConfig.h +488 -488
- package/ios/styles/StyleConfig.mm +2820 -2820
- package/ios/utils/AccessibilityInfo.h +35 -35
- package/ios/utils/AccessibilityInfo.m +24 -24
- package/ios/utils/BlockquoteBorder.h +26 -26
- package/ios/utils/BlockquoteBorder.m +294 -294
- package/ios/utils/CodeBackground.h +19 -19
- package/ios/utils/CodeBackground.m +196 -196
- package/ios/utils/CodeBlockBackground.h +17 -17
- package/ios/utils/CodeBlockBackground.m +102 -102
- package/ios/utils/ContextMenuUtils.h +76 -76
- package/ios/utils/ContextMenuUtils.mm +75 -75
- package/ios/utils/ENRMAccessibilityLabels.h +40 -40
- package/ios/utils/ENRMAccessibilityLabels.m +5 -5
- package/ios/utils/ENRMAsyncRenderCoordinator.h +24 -24
- package/ios/utils/ENRMAsyncRenderCoordinator.m +37 -37
- package/ios/utils/ENRMAtomicSize.h +65 -65
- package/ios/utils/ENRMCodeBlockContent.h +37 -37
- package/ios/utils/ENRMCodeBlockContent.mm +89 -89
- package/ios/utils/ENRMFeatureFlags.h +25 -25
- package/ios/utils/ENRMImageDownloader.h +30 -30
- package/ios/utils/ENRMImageDownloader.m +168 -168
- package/ios/utils/ENRMLatexErrorCoordinator.h +27 -27
- package/ios/utils/ENRMLatexErrorCoordinator.mm +75 -75
- package/ios/utils/ENRMLatexErrorReporting.h +13 -13
- package/ios/utils/ENRMLinkContextMenus.h +93 -93
- package/ios/utils/ENRMLinkContextMenus.m +178 -178
- package/ios/utils/ENRMLinkRegexConfig.h +30 -30
- package/ios/utils/ENRMLinkRegexConfig.mm +104 -104
- package/ios/utils/ENRMLinkRegexProps.h +23 -23
- package/ios/utils/ENRMLocalImageLoader.h +35 -35
- package/ios/utils/ENRMLocalImageLoader.m +111 -111
- package/ios/utils/ENRMMenuAction.h +27 -27
- package/ios/utils/ENRMMenuAction.m +33 -33
- package/ios/utils/ENRMSpoilerOverlayManager.h +15 -15
- package/ios/utils/ENRMSpoilerOverlayManager.m +19 -19
- package/ios/utils/ENRMSpoilerTapUtils.h +6 -6
- package/ios/utils/ENRMSpoilerTapUtils.m +11 -11
- package/ios/utils/ENRMTailFadeInAnimator.h +16 -16
- package/ios/utils/ENRMTailFadeInAnimator.m +161 -161
- package/ios/utils/ENRMTextHitTest.h +23 -23
- package/ios/utils/ENRMTextHitTest.m +20 -20
- package/ios/utils/ENRMTextInteractionUtils.h +20 -20
- package/ios/utils/ENRMTextInteractionUtils.m +15 -15
- package/ios/utils/ENRMTextRenderer.h +38 -38
- package/ios/utils/ENRMTextRenderer.m +54 -54
- package/ios/utils/ENRMTextViewSetup.h +132 -132
- package/ios/utils/ENRMUIKit.h +429 -429
- package/ios/utils/EditMenuUtils.h +105 -105
- package/ios/utils/EditMenuUtils.m +143 -143
- package/ios/utils/FontScaleObserver.h +10 -10
- package/ios/utils/FontScaleObserver.m +55 -55
- package/ios/utils/FontUtils.h +31 -31
- package/ios/utils/FontUtils.m +63 -63
- package/ios/utils/HTMLGenerator.h +25 -25
- package/ios/utils/HTMLGenerator.m +1041 -1041
- package/ios/utils/HeightUpdateUtils.h +25 -25
- package/ios/utils/ImageRequestHeaderUtils.h +35 -35
- package/ios/utils/LastElementUtils.h +97 -97
- package/ios/utils/LinkContextMenuUtils.h +55 -55
- package/ios/utils/LinkPillContentUtils.h +46 -46
- package/ios/utils/ListMarkerDrawer.h +15 -15
- package/ios/utils/ListMarkerDrawer.m +239 -239
- package/ios/utils/MentionBackground.h +26 -26
- package/ios/utils/MentionBackground.m +86 -86
- package/ios/utils/ParagraphStyleUtils.h +87 -87
- package/ios/utils/ParagraphStyleUtils.m +484 -484
- package/ios/utils/PasteboardUtils.h +48 -48
- package/ios/utils/PasteboardUtils.m +166 -166
- package/ios/utils/RTFExportUtils.h +24 -24
- package/ios/utils/RTFExportUtils.m +299 -299
- package/ios/utils/SelectionColorUtils.h +14 -14
- package/ios/utils/StylePropsUtils.h +1340 -1340
- package/ios/utils/TaskListTapUtils.h +6 -6
- package/ios/utils/TaskListTapUtils.m +14 -14
- package/ios/utils/TextViewLayoutManager.h +14 -14
- package/ios/utils/TiptapAccessibilityElementBuilder.h +43 -43
- package/ios/utils/TiptapAccessibilityElementBuilder.m +432 -432
- package/ios/utils/TiptapExtractor.h +17 -17
- package/ios/utils/TiptapExtractor.m +367 -367
- package/ios/views/ENRMTiptapTextView.h +25 -25
- package/ios/views/ENRMTiptapTextView.m +247 -247
- package/package.json +65 -70
- package/react-native.config.js +10 -10
- package/src/admonitionDefaults.ts +58 -58
- package/src/darkModeTextStyle.ts +99 -99
- package/src/headingDefaults.ts +21 -21
- package/src/index.tsx +4 -4
- package/src/linkVariantUtils.ts +120 -120
- package/src/normalizeTiptapStyle.ts +397 -397
- package/src/rn-globals.d.ts +1 -1
- package/src/styleUtils.ts +107 -107
- package/src/types/TiptapStyle.ts +532 -532
- package/src/types/TiptapStyleInternal.ts +299 -299
- package/src/types/linkPill.ts +9 -9
- package/src/utils/isDev.ts +4 -4
|
@@ -1,294 +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
|
|
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
|
|
@@ -1,19 +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
|
|
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
|