@mathers101/react-native-render-rich-text 0.1.9 → 0.1.14
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +20 -20
- package/README.md +140 -140
- package/ReactNativeRenderRichText.podspec +23 -23
- package/android/build.gradle +86 -86
- package/android/consumer-rules.pro +3 -3
- package/android/src/main/AndroidManifest.xml +2 -2
- package/android/src/main/java/com/renderrichtext/EnrichedTiptapTextLayoutManager.kt +24 -24
- package/android/src/main/java/com/renderrichtext/EnrichedTiptapTextPackage.kt +13 -13
- package/android/src/main/java/com/renderrichtext/MeasurementStore.kt +644 -644
- package/android/src/main/java/com/renderrichtext/accessibility/AccessibilityLabels.kt +17 -17
- package/android/src/main/java/com/renderrichtext/accessibility/AccessibleTiptapTextView.kt +112 -112
- package/android/src/main/java/com/renderrichtext/accessibility/TiptapAccessibilityHelper.kt +576 -576
- package/android/src/main/java/com/renderrichtext/events/CodeBlockPressEvent.kt +24 -24
- package/android/src/main/java/com/renderrichtext/events/ContextMenuItemPressEvent.kt +28 -28
- package/android/src/main/java/com/renderrichtext/events/CopyPressEvent.kt +24 -24
- package/android/src/main/java/com/renderrichtext/events/ImagePressEvent.kt +25 -25
- package/android/src/main/java/com/renderrichtext/events/LatexErrorEvent.kt +29 -29
- package/android/src/main/java/com/renderrichtext/events/LinkLongPressEvent.kt +23 -23
- package/android/src/main/java/com/renderrichtext/events/LinkPressEvent.kt +23 -23
- package/android/src/main/java/com/renderrichtext/events/MentionLongPressEvent.kt +25 -25
- package/android/src/main/java/com/renderrichtext/events/MentionPressEvent.kt +25 -25
- package/android/src/main/java/com/renderrichtext/events/TaskListItemPressEvent.kt +26 -26
- package/android/src/main/java/com/renderrichtext/math/LatexErrorReporter.kt +9 -9
- package/android/src/main/java/com/renderrichtext/parser/Parser.kt +59 -59
- package/android/src/main/java/com/renderrichtext/parser/TextLinkMatching.kt +35 -35
- package/android/src/main/java/com/renderrichtext/renderer/BaselineShiftRenderer.kt +45 -45
- package/android/src/main/java/com/renderrichtext/renderer/BlankLineRenderer.kt +39 -39
- package/android/src/main/java/com/renderrichtext/renderer/BlockquoteRenderer.kt +243 -243
- package/android/src/main/java/com/renderrichtext/renderer/BlockquoteTextRenderer.kt +56 -56
- package/android/src/main/java/com/renderrichtext/renderer/CodeBlockRenderer.kt +135 -135
- package/android/src/main/java/com/renderrichtext/renderer/CodeRenderer.kt +37 -37
- package/android/src/main/java/com/renderrichtext/renderer/EmphasisRenderer.kt +28 -28
- package/android/src/main/java/com/renderrichtext/renderer/HeadingRenderer.kt +81 -81
- package/android/src/main/java/com/renderrichtext/renderer/HighlightRenderer.kt +26 -26
- package/android/src/main/java/com/renderrichtext/renderer/LineBreakRenderer.kt +17 -17
- package/android/src/main/java/com/renderrichtext/renderer/LinkRenderer.kt +90 -90
- package/android/src/main/java/com/renderrichtext/renderer/ListContextManager.kt +109 -109
- package/android/src/main/java/com/renderrichtext/renderer/ListItemRenderer.kt +211 -211
- package/android/src/main/java/com/renderrichtext/renderer/ListRenderer.kt +133 -133
- package/android/src/main/java/com/renderrichtext/renderer/MentionRenderer.kt +85 -85
- package/android/src/main/java/com/renderrichtext/renderer/ParagraphRenderer.kt +91 -91
- package/android/src/main/java/com/renderrichtext/renderer/Renderer.kt +148 -148
- package/android/src/main/java/com/renderrichtext/renderer/SoftBreakRenderer.kt +17 -17
- package/android/src/main/java/com/renderrichtext/renderer/SpanStyleCache.kt +143 -143
- package/android/src/main/java/com/renderrichtext/renderer/StrikethroughRenderer.kt +28 -28
- package/android/src/main/java/com/renderrichtext/renderer/StrongRenderer.kt +28 -28
- package/android/src/main/java/com/renderrichtext/renderer/TextRenderer.kt +31 -31
- package/android/src/main/java/com/renderrichtext/renderer/ThematicBreakRenderer.kt +46 -46
- package/android/src/main/java/com/renderrichtext/renderer/UnderlineRenderer.kt +28 -28
- package/android/src/main/java/com/renderrichtext/spans/BaseListSpan.kt +164 -164
- package/android/src/main/java/com/renderrichtext/spans/BaselineShiftSpan.kt +27 -27
- package/android/src/main/java/com/renderrichtext/spans/BlockquoteSpan.kt +302 -302
- package/android/src/main/java/com/renderrichtext/spans/CodeBackgroundSpan.kt +205 -205
- package/android/src/main/java/com/renderrichtext/spans/CodeBlockSpan.kt +216 -216
- package/android/src/main/java/com/renderrichtext/spans/CodeSpan.kt +32 -32
- package/android/src/main/java/com/renderrichtext/spans/EmphasisSpan.kt +42 -42
- package/android/src/main/java/com/renderrichtext/spans/FadeInSpan.kt +29 -29
- package/android/src/main/java/com/renderrichtext/spans/HeadingSpan.kt +38 -38
- package/android/src/main/java/com/renderrichtext/spans/HighlightSpan.kt +80 -80
- package/android/src/main/java/com/renderrichtext/spans/ImageSpan.kt +481 -481
- package/android/src/main/java/com/renderrichtext/spans/InlineBackgroundGeometry.kt +42 -42
- package/android/src/main/java/com/renderrichtext/spans/LineHeightSpan.kt +39 -39
- package/android/src/main/java/com/renderrichtext/spans/LinkPillIconCache.kt +154 -154
- package/android/src/main/java/com/renderrichtext/spans/LinkPillSpan.kt +381 -381
- package/android/src/main/java/com/renderrichtext/spans/LinkSpan.kt +68 -68
- package/android/src/main/java/com/renderrichtext/spans/ListItemSpacingSpan.kt +33 -33
- package/android/src/main/java/com/renderrichtext/spans/ListMarkerAnchorSpan.kt +38 -38
- package/android/src/main/java/com/renderrichtext/spans/MarginBottomSpan.kt +76 -76
- package/android/src/main/java/com/renderrichtext/spans/MentionChipSpan.kt +132 -132
- package/android/src/main/java/com/renderrichtext/spans/MentionSpan.kt +46 -46
- package/android/src/main/java/com/renderrichtext/spans/OrderedListSpan.kt +127 -127
- package/android/src/main/java/com/renderrichtext/spans/SpoilerSpan.kt +33 -33
- package/android/src/main/java/com/renderrichtext/spans/StrikethroughSpan.kt +12 -12
- package/android/src/main/java/com/renderrichtext/spans/StrongSpan.kt +39 -39
- package/android/src/main/java/com/renderrichtext/spans/TaskListSpan.kt +143 -143
- package/android/src/main/java/com/renderrichtext/spans/TextSpan.kt +26 -26
- package/android/src/main/java/com/renderrichtext/spans/ThematicBreakSpan.kt +69 -69
- package/android/src/main/java/com/renderrichtext/spans/UnorderedListSpan.kt +96 -96
- package/android/src/main/java/com/renderrichtext/spoiler/SpoilerStubs.kt +46 -46
- package/android/src/main/java/com/renderrichtext/styles/BaseBlockStyle.kt +11 -11
- package/android/src/main/java/com/renderrichtext/styles/BlockquoteStyle.kt +83 -83
- package/android/src/main/java/com/renderrichtext/styles/CodeBlockStyle.kt +80 -80
- package/android/src/main/java/com/renderrichtext/styles/CodeStyle.kt +26 -26
- package/android/src/main/java/com/renderrichtext/styles/EmphasisStyle.kt +21 -21
- package/android/src/main/java/com/renderrichtext/styles/FactoidStyle.kt +21 -21
- package/android/src/main/java/com/renderrichtext/styles/HeadingStyle.kt +33 -33
- package/android/src/main/java/com/renderrichtext/styles/HighlightStyle.kt +19 -19
- package/android/src/main/java/com/renderrichtext/styles/ImageStyle.kt +29 -29
- package/android/src/main/java/com/renderrichtext/styles/InlineImageStyle.kt +17 -17
- package/android/src/main/java/com/renderrichtext/styles/InlineMathStyle.kt +17 -17
- package/android/src/main/java/com/renderrichtext/styles/LinkPillContent.kt +36 -36
- package/android/src/main/java/com/renderrichtext/styles/LinkPillStyle.kt +44 -44
- package/android/src/main/java/com/renderrichtext/styles/LinkStyle.kt +23 -23
- package/android/src/main/java/com/renderrichtext/styles/LinkVariantEntry.kt +34 -34
- package/android/src/main/java/com/renderrichtext/styles/ListStyle.kt +65 -65
- package/android/src/main/java/com/renderrichtext/styles/MathStyle.kt +29 -29
- package/android/src/main/java/com/renderrichtext/styles/MentionStyle.kt +19 -19
- package/android/src/main/java/com/renderrichtext/styles/ParagraphStyle.kt +33 -33
- package/android/src/main/java/com/renderrichtext/styles/SpoilerStyle.kt +27 -27
- package/android/src/main/java/com/renderrichtext/styles/StrikethroughStyle.kt +17 -17
- package/android/src/main/java/com/renderrichtext/styles/StrongStyle.kt +21 -21
- package/android/src/main/java/com/renderrichtext/styles/StyleConfig.kt +411 -411
- package/android/src/main/java/com/renderrichtext/styles/StyleParser.kt +92 -92
- package/android/src/main/java/com/renderrichtext/styles/SubscriptStyle.kt +16 -16
- package/android/src/main/java/com/renderrichtext/styles/SuperscriptStyle.kt +16 -16
- package/android/src/main/java/com/renderrichtext/styles/TableStyle.kt +75 -75
- package/android/src/main/java/com/renderrichtext/styles/TaskListStyle.kt +29 -29
- package/android/src/main/java/com/renderrichtext/styles/TextAlignment.kt +32 -32
- package/android/src/main/java/com/renderrichtext/styles/ThematicBreakStyle.kt +23 -23
- package/android/src/main/java/com/renderrichtext/styles/UnderlineStyle.kt +17 -17
- package/android/src/main/java/com/renderrichtext/styles/VideoStyle.kt +31 -31
- package/android/src/main/java/com/renderrichtext/utils/common/BorderStyleUtils.kt +86 -86
- package/android/src/main/java/com/renderrichtext/utils/common/BreakStrategyUtils.kt +32 -32
- package/android/src/main/java/com/renderrichtext/utils/common/CodeBlockHighlighter.kt +36 -36
- package/android/src/main/java/com/renderrichtext/utils/common/CodeBlockNode.kt +42 -42
- package/android/src/main/java/com/renderrichtext/utils/common/EllipsizeUtils.kt +27 -27
- package/android/src/main/java/com/renderrichtext/utils/common/EnrichedTiptapAncestorUtils.kt +10 -10
- package/android/src/main/java/com/renderrichtext/utils/common/FeatureFlags.kt +9 -9
- package/android/src/main/java/com/renderrichtext/utils/common/LinkRecognitionProps.kt +31 -31
- package/android/src/main/java/com/renderrichtext/utils/common/LinkRegexConfig.kt +56 -56
- package/android/src/main/java/com/renderrichtext/utils/common/MotionPreferences.kt +18 -18
- package/android/src/main/java/com/renderrichtext/utils/common/ReadableMapExtensions.kt +28 -28
- package/android/src/main/java/com/renderrichtext/utils/common/layout/RTLUtils.kt +6 -6
- package/android/src/main/java/com/renderrichtext/utils/common/serialization/TiptapASTSerializer.kt +368 -368
- package/android/src/main/java/com/renderrichtext/utils/text/ImageCache.kt +88 -88
- package/android/src/main/java/com/renderrichtext/utils/text/ImageDownloader.kt +203 -203
- package/android/src/main/java/com/renderrichtext/utils/text/LocalImageLoader.kt +167 -167
- package/android/src/main/java/com/renderrichtext/utils/text/TailFadeInAnimator.kt +84 -84
- package/android/src/main/java/com/renderrichtext/utils/text/conversion/HTMLGenerator.kt +1105 -1105
- package/android/src/main/java/com/renderrichtext/utils/text/conversion/TiptapExtractor.kt +423 -423
- package/android/src/main/java/com/renderrichtext/utils/text/extensions/ParagraphUtils.kt +9 -9
- package/android/src/main/java/com/renderrichtext/utils/text/extensions/SpannableExtensions.kt +9 -9
- package/android/src/main/java/com/renderrichtext/utils/text/extensions/TextPaintExtensions.kt +76 -76
- package/android/src/main/java/com/renderrichtext/utils/text/interaction/CheckboxTouchHelper.kt +61 -61
- package/android/src/main/java/com/renderrichtext/utils/text/interaction/TaskListTapUtils.kt +286 -286
- package/android/src/main/java/com/renderrichtext/utils/text/span/ApplyLineHeight.kt +39 -39
- package/android/src/main/java/com/renderrichtext/utils/text/span/BlockSpacing.kt +142 -142
- package/android/src/main/java/com/renderrichtext/utils/text/span/SpanFlags.kt +43 -43
- package/android/src/main/java/com/renderrichtext/utils/text/span/WidthAwareSpans.kt +30 -30
- package/android/src/main/java/com/renderrichtext/utils/text/view/CodeBlockPressHost.kt +15 -15
- package/android/src/main/java/com/renderrichtext/utils/text/view/ImagePressHost.kt +19 -19
- package/android/src/main/java/com/renderrichtext/utils/text/view/SelectionActionMode.kt +235 -235
- package/android/src/main/java/com/renderrichtext/utils/text/view/TextSelectionColors.kt +48 -48
- package/android/src/main/java/com/renderrichtext/utils/text/view/TextViewSetup.kt +119 -119
- package/android/src/main/java/com/renderrichtext/views/ContextMenuPopup.kt +217 -217
- package/android/src/main/java/com/renderrichtext/views/CopyGlyph.kt +101 -101
- package/android/src/main/java/com/renderrichtext/views/WrapGlyph.kt +40 -40
- package/android/src/main/jni/CMakeLists.txt +52 -52
- package/android/src/main/jni/react/renderer/components/RichTextSpec/ComponentDescriptors.h +30 -30
- package/android/src/main/jni/react/renderer/components/RichTextSpec/TiptapTextComponentDescriptor.h +29 -29
- package/android/src/main/jni/react/renderer/components/RichTextSpec/TiptapTextMeasurementManager.cpp +45 -45
- package/android/src/main/jni/react/renderer/components/RichTextSpec/TiptapTextMeasurementManager.h +21 -21
- package/android/src/main/jni/react/renderer/components/RichTextSpec/TiptapTextShadowNode.cpp +38 -38
- package/android/src/main/jni/react/renderer/components/RichTextSpec/TiptapTextShadowNode.h +53 -53
- package/android/src/main/jni/react/renderer/components/RichTextSpec/TiptapTextState.cpp +9 -9
- package/android/src/main/jni/react/renderer/components/RichTextSpec/TiptapTextState.h +24 -24
- package/android/src/main/jni/react/renderer/components/RichTextSpec/conversions.h +40 -40
- package/cpp/parser/TiptapParser.hpp +13 -13
- package/cpp/vendor/nlohmann/json.hpp +24765 -24765
- package/ios/EnrichedTiptapText.h +27 -27
- package/ios/attachments/ENRMImageAttachment.h +51 -51
- package/ios/attachments/ENRMImageAttachment.m +398 -398
- package/ios/attachments/ENRMLinkPillAttachment.h +47 -47
- package/ios/attachments/ENRMLinkPillAttachment.m +324 -324
- package/ios/attachments/ENRMLinkPillIconCache.h +28 -28
- package/ios/attachments/ENRMLinkPillIconCache.m +181 -181
- package/ios/attachments/ENRMLinkPillText.h +27 -27
- package/ios/attachments/ENRMLinkPillText.m +118 -118
- package/ios/attachments/ENRMMathInlineAttachment.h +7 -7
- package/ios/attachments/ENRMMathInlineAttachment.m +4 -4
- package/ios/attachments/ThematicBreakAttachment.h +15 -15
- package/ios/attachments/ThematicBreakAttachment.m +33 -33
- package/ios/internals/ENRMViewFreeMeasurement.h +208 -208
- package/ios/internals/EnrichedTiptapTextComponentDescriptor.h +19 -19
- package/ios/internals/EnrichedTiptapTextShadowNode.h +43 -43
- package/ios/internals/EnrichedTiptapTextShadowNode.mm +69 -69
- package/ios/internals/EnrichedTiptapTextState.h +24 -24
- package/ios/internals/MeasurementCache.h +308 -308
- package/ios/internals/ShadowMeasurementUtils.h +145 -145
- package/ios/parser/ENRMTextLinkAttributes.h +7 -7
- package/ios/parser/ENRMTiptapParser.h +33 -33
- package/ios/parser/ENRMTiptapParser.mm +73 -73
- package/ios/parser/TiptapASTNode.m +52 -52
- package/ios/renderer/AttributedRenderer.h +23 -23
- package/ios/renderer/AttributedRenderer.m +229 -229
- package/ios/renderer/BaseRenderer.h +33 -33
- package/ios/renderer/BaseRenderer.m +46 -46
- package/ios/renderer/BaselineShiftTextAttributes.h +10 -10
- package/ios/renderer/BaselineShiftTextAttributes.m +26 -26
- package/ios/renderer/BlankLineRenderer.h +4 -4
- package/ios/renderer/BlankLineRenderer.m +51 -51
- package/ios/renderer/BlockquoteRenderer.h +6 -6
- package/ios/renderer/BlockquoteRenderer.m +258 -258
- package/ios/renderer/CodeBlockRenderer.h +9 -9
- package/ios/renderer/CodeBlockRenderer.m +99 -99
- package/ios/renderer/CodeRenderer.h +9 -9
- package/ios/renderer/CodeRenderer.m +69 -69
- package/ios/renderer/ENRMBlockquoteTextRenderer.h +25 -25
- package/ios/renderer/ENRMBlockquoteTextRenderer.m +48 -48
- package/ios/renderer/EmphasisRenderer.h +5 -5
- package/ios/renderer/EmphasisRenderer.m +99 -99
- package/ios/renderer/HeadingRenderer.h +6 -6
- package/ios/renderer/HeadingRenderer.m +102 -102
- package/ios/renderer/HighlightRenderer.h +7 -7
- package/ios/renderer/HighlightRenderer.m +33 -33
- package/ios/renderer/LinkRenderer.h +6 -6
- package/ios/renderer/LinkRenderer.m +157 -157
- package/ios/renderer/ListItemRenderer.h +24 -24
- package/ios/renderer/ListItemRenderer.m +283 -283
- package/ios/renderer/ListRenderer.h +13 -13
- package/ios/renderer/ListRenderer.m +126 -126
- package/ios/renderer/MentionRenderer.h +9 -9
- package/ios/renderer/MentionRenderer.m +96 -96
- package/ios/renderer/NodeRenderer.h +8 -8
- package/ios/renderer/ParagraphRenderer.h +6 -6
- package/ios/renderer/ParagraphRenderer.m +85 -85
- package/ios/renderer/RenderContext.h +145 -145
- package/ios/renderer/RenderContext.m +402 -402
- package/ios/renderer/RendererFactory.h +12 -12
- package/ios/renderer/StrikethroughRenderer.h +5 -5
- package/ios/renderer/StrikethroughRenderer.m +30 -30
- package/ios/renderer/StrongRenderer.h +5 -5
- package/ios/renderer/StrongRenderer.m +87 -87
- package/ios/renderer/TextRenderer.h +6 -6
- package/ios/renderer/TextRenderer.m +18 -18
- package/ios/renderer/ThematicBreakRenderer.h +4 -4
- package/ios/renderer/ThematicBreakRenderer.m +41 -41
- package/ios/renderer/UnderlineRenderer.h +4 -4
- package/ios/renderer/UnderlineRenderer.m +41 -41
- package/ios/styles/ENRMFontSlot.h +12 -12
- package/ios/styles/ENRMFontSlot.m +24 -24
- package/ios/styles/StyleConfig.h +488 -488
- package/ios/styles/StyleConfig.mm +2820 -2820
- package/ios/utils/AccessibilityInfo.h +35 -35
- package/ios/utils/AccessibilityInfo.m +24 -24
- package/ios/utils/BlockquoteBorder.h +26 -26
- package/ios/utils/BlockquoteBorder.m +294 -294
- package/ios/utils/CodeBackground.h +19 -19
- package/ios/utils/CodeBackground.m +196 -196
- package/ios/utils/CodeBlockBackground.h +17 -17
- package/ios/utils/CodeBlockBackground.m +102 -102
- package/ios/utils/ContextMenuUtils.h +76 -76
- package/ios/utils/ContextMenuUtils.mm +75 -75
- package/ios/utils/ENRMAccessibilityLabels.h +40 -40
- package/ios/utils/ENRMAccessibilityLabels.m +5 -5
- package/ios/utils/ENRMAsyncRenderCoordinator.h +24 -24
- package/ios/utils/ENRMAsyncRenderCoordinator.m +37 -37
- package/ios/utils/ENRMAtomicSize.h +65 -65
- package/ios/utils/ENRMCodeBlockContent.h +37 -37
- package/ios/utils/ENRMCodeBlockContent.mm +89 -89
- package/ios/utils/ENRMFeatureFlags.h +25 -25
- package/ios/utils/ENRMImageDownloader.h +30 -30
- package/ios/utils/ENRMImageDownloader.m +168 -168
- package/ios/utils/ENRMLatexErrorCoordinator.h +27 -27
- package/ios/utils/ENRMLatexErrorCoordinator.mm +75 -75
- package/ios/utils/ENRMLatexErrorReporting.h +13 -13
- package/ios/utils/ENRMLinkContextMenus.h +93 -93
- package/ios/utils/ENRMLinkContextMenus.m +178 -178
- package/ios/utils/ENRMLinkRegexConfig.h +30 -30
- package/ios/utils/ENRMLinkRegexConfig.mm +104 -104
- package/ios/utils/ENRMLinkRegexProps.h +23 -23
- package/ios/utils/ENRMLocalImageLoader.h +35 -35
- package/ios/utils/ENRMLocalImageLoader.m +111 -111
- package/ios/utils/ENRMMenuAction.h +27 -27
- package/ios/utils/ENRMMenuAction.m +33 -33
- package/ios/utils/ENRMSpoilerOverlayManager.h +15 -15
- package/ios/utils/ENRMSpoilerOverlayManager.m +19 -19
- package/ios/utils/ENRMSpoilerTapUtils.h +6 -6
- package/ios/utils/ENRMSpoilerTapUtils.m +11 -11
- package/ios/utils/ENRMTailFadeInAnimator.h +16 -16
- package/ios/utils/ENRMTailFadeInAnimator.m +161 -161
- package/ios/utils/ENRMTextHitTest.h +23 -23
- package/ios/utils/ENRMTextHitTest.m +20 -20
- package/ios/utils/ENRMTextInteractionUtils.h +20 -20
- package/ios/utils/ENRMTextInteractionUtils.m +15 -15
- package/ios/utils/ENRMTextRenderer.h +38 -38
- package/ios/utils/ENRMTextRenderer.m +54 -54
- package/ios/utils/ENRMTextViewSetup.h +132 -132
- package/ios/utils/ENRMUIKit.h +429 -429
- package/ios/utils/EditMenuUtils.h +105 -105
- package/ios/utils/EditMenuUtils.m +143 -143
- package/ios/utils/FontScaleObserver.h +10 -10
- package/ios/utils/FontScaleObserver.m +55 -55
- package/ios/utils/FontUtils.h +31 -31
- package/ios/utils/FontUtils.m +63 -63
- package/ios/utils/HTMLGenerator.h +25 -25
- package/ios/utils/HTMLGenerator.m +1041 -1041
- package/ios/utils/HeightUpdateUtils.h +25 -25
- package/ios/utils/ImageRequestHeaderUtils.h +35 -35
- package/ios/utils/LastElementUtils.h +97 -97
- package/ios/utils/LinkContextMenuUtils.h +55 -55
- package/ios/utils/LinkPillContentUtils.h +46 -46
- package/ios/utils/ListMarkerDrawer.h +15 -15
- package/ios/utils/ListMarkerDrawer.m +239 -239
- package/ios/utils/MentionBackground.h +26 -26
- package/ios/utils/MentionBackground.m +86 -86
- package/ios/utils/ParagraphStyleUtils.h +87 -87
- package/ios/utils/ParagraphStyleUtils.m +484 -484
- package/ios/utils/PasteboardUtils.h +48 -48
- package/ios/utils/PasteboardUtils.m +166 -166
- package/ios/utils/RTFExportUtils.h +24 -24
- package/ios/utils/RTFExportUtils.m +299 -299
- package/ios/utils/SelectionColorUtils.h +14 -14
- package/ios/utils/StylePropsUtils.h +1340 -1340
- package/ios/utils/TaskListTapUtils.h +6 -6
- package/ios/utils/TaskListTapUtils.m +14 -14
- package/ios/utils/TextViewLayoutManager.h +14 -14
- package/ios/utils/TiptapAccessibilityElementBuilder.h +43 -43
- package/ios/utils/TiptapAccessibilityElementBuilder.m +432 -432
- package/ios/utils/TiptapExtractor.h +17 -17
- package/ios/utils/TiptapExtractor.m +367 -367
- package/ios/views/ENRMTiptapTextView.h +25 -25
- package/ios/views/ENRMTiptapTextView.m +247 -247
- package/package.json +65 -70
- package/react-native.config.js +10 -10
- package/src/admonitionDefaults.ts +58 -58
- package/src/darkModeTextStyle.ts +99 -99
- package/src/headingDefaults.ts +21 -21
- package/src/index.tsx +4 -4
- package/src/linkVariantUtils.ts +120 -120
- package/src/normalizeTiptapStyle.ts +397 -397
- package/src/rn-globals.d.ts +1 -1
- package/src/styleUtils.ts +107 -107
- package/src/types/TiptapStyle.ts +532 -532
- package/src/types/TiptapStyleInternal.ts +299 -299
- package/src/types/linkPill.ts +9 -9
- package/src/utils/isDev.ts +4 -4
|
@@ -1,23 +1,23 @@
|
|
|
1
|
-
#import <Foundation/Foundation.h>
|
|
2
|
-
|
|
3
|
-
@class ENRMBlockquoteTextRenderer;
|
|
4
|
-
@class TiptapASTNode;
|
|
5
|
-
@class RenderContext;
|
|
6
|
-
|
|
7
|
-
NS_ASSUME_NONNULL_BEGIN
|
|
8
|
-
|
|
9
|
-
@interface AttributedRenderer : NSObject
|
|
10
|
-
- (instancetype)initWithConfig:(id)config;
|
|
11
|
-
// Renders a flat list of sibling nodes into an attributed string: sets the baseline block style,
|
|
12
|
-
// walks each node, and trims the trailing block margin. Pass a non-nil block to render the nodes as
|
|
13
|
-
// a blockquote's own content (blockquote baseline + the quote's line height applied over the run);
|
|
14
|
-
// it draws no box - the ENRMBlockquoteContainerView draws the border/background/padding. See
|
|
15
|
-
// ENRMBlockquoteTextRenderer.
|
|
16
|
-
- (NSMutableAttributedString *)renderNodes:(NSArray<TiptapASTNode *> *)nodes
|
|
17
|
-
context:(RenderContext *)context
|
|
18
|
-
block:(nullable ENRMBlockquoteTextRenderer *)block;
|
|
19
|
-
- (CGFloat)getLastElementMarginBottom;
|
|
20
|
-
- (void)setAllowTrailingMargin:(BOOL)allow;
|
|
21
|
-
@end
|
|
22
|
-
|
|
23
|
-
NS_ASSUME_NONNULL_END
|
|
1
|
+
#import <Foundation/Foundation.h>
|
|
2
|
+
|
|
3
|
+
@class ENRMBlockquoteTextRenderer;
|
|
4
|
+
@class TiptapASTNode;
|
|
5
|
+
@class RenderContext;
|
|
6
|
+
|
|
7
|
+
NS_ASSUME_NONNULL_BEGIN
|
|
8
|
+
|
|
9
|
+
@interface AttributedRenderer : NSObject
|
|
10
|
+
- (instancetype)initWithConfig:(id)config;
|
|
11
|
+
// Renders a flat list of sibling nodes into an attributed string: sets the baseline block style,
|
|
12
|
+
// walks each node, and trims the trailing block margin. Pass a non-nil block to render the nodes as
|
|
13
|
+
// a blockquote's own content (blockquote baseline + the quote's line height applied over the run);
|
|
14
|
+
// it draws no box - the ENRMBlockquoteContainerView draws the border/background/padding. See
|
|
15
|
+
// ENRMBlockquoteTextRenderer.
|
|
16
|
+
- (NSMutableAttributedString *)renderNodes:(NSArray<TiptapASTNode *> *)nodes
|
|
17
|
+
context:(RenderContext *)context
|
|
18
|
+
block:(nullable ENRMBlockquoteTextRenderer *)block;
|
|
19
|
+
- (CGFloat)getLastElementMarginBottom;
|
|
20
|
+
- (void)setAllowTrailingMargin:(BOOL)allow;
|
|
21
|
+
@end
|
|
22
|
+
|
|
23
|
+
NS_ASSUME_NONNULL_END
|
|
@@ -1,229 +1,229 @@
|
|
|
1
|
-
#import "AttributedRenderer.h"
|
|
2
|
-
#import "BlockquoteBorder.h"
|
|
3
|
-
#import "CodeBlockBackground.h"
|
|
4
|
-
#import "ENRMBlockquoteTextRenderer.h"
|
|
5
|
-
#import "ENRMLinkPillText.h"
|
|
6
|
-
#import "LastElementUtils.h"
|
|
7
|
-
#import "TiptapASTNode.h"
|
|
8
|
-
#import "NodeRenderer.h"
|
|
9
|
-
#import "ParagraphStyleUtils.h"
|
|
10
|
-
#import "RenderContext.h"
|
|
11
|
-
#import "RendererFactory.h"
|
|
12
|
-
#import "StyleConfig.h"
|
|
13
|
-
|
|
14
|
-
@implementation AttributedRenderer {
|
|
15
|
-
StyleConfig *_config;
|
|
16
|
-
RendererFactory *_rendererFactory;
|
|
17
|
-
CGFloat _lastElementMarginBottom;
|
|
18
|
-
BOOL _allowTrailingMargin;
|
|
19
|
-
}
|
|
20
|
-
|
|
21
|
-
- (instancetype)initWithConfig:(StyleConfig *)config
|
|
22
|
-
{
|
|
23
|
-
self = [super init];
|
|
24
|
-
if (self) {
|
|
25
|
-
_config = config;
|
|
26
|
-
_rendererFactory = [[RendererFactory alloc] initWithConfig:config];
|
|
27
|
-
_lastElementMarginBottom = 0.0;
|
|
28
|
-
_allowTrailingMargin = NO;
|
|
29
|
-
}
|
|
30
|
-
return self;
|
|
31
|
-
}
|
|
32
|
-
|
|
33
|
-
/**
|
|
34
|
-
* Entry point for rendering a flat list of sibling nodes (e.g. a document's or a block segment's
|
|
35
|
-
* children). Sets the baseline block style, runs the recursive traversal, and trims the trailing
|
|
36
|
-
* block margin. An optional [block] decorates the pass - it enters a block baseline before the nodes
|
|
37
|
-
* render and post-processes the finished string - letting a caller render content as e.g. blockquote
|
|
38
|
-
* text without this class knowing anything block-specific. See ENRMBlockquoteTextRenderer.
|
|
39
|
-
*/
|
|
40
|
-
- (NSMutableAttributedString *)renderNodes:(NSArray<TiptapASTNode *> *)nodes
|
|
41
|
-
context:(RenderContext *)context
|
|
42
|
-
block:(ENRMBlockquoteTextRenderer *)block
|
|
43
|
-
{
|
|
44
|
-
// 1. Establish the baseline block style. This ensures leaf nodes (like Text) have valid
|
|
45
|
-
// attributes if they appear at the top level. A decorator overrides the default paragraph
|
|
46
|
-
// baseline (e.g. the blockquote baseline so paragraphs render tight and pick up the quote's
|
|
47
|
-
// font/color).
|
|
48
|
-
if (block) {
|
|
49
|
-
[block pushOnContext:context];
|
|
50
|
-
} else {
|
|
51
|
-
[context setBlockStyle:BlockTypeParagraph font:_config.paragraphFont color:_config.paragraphColor headingLevel:0];
|
|
52
|
-
}
|
|
53
|
-
|
|
54
|
-
NSMutableAttributedString *output = [[NSMutableAttributedString alloc] init];
|
|
55
|
-
|
|
56
|
-
// 2. Iterate through the sibling nodes.
|
|
57
|
-
for (TiptapASTNode *node in nodes) {
|
|
58
|
-
[self renderNodeRecursive:node into:output context:context];
|
|
59
|
-
}
|
|
60
|
-
|
|
61
|
-
// 3. Remove trailing paragraph spacing from last block element
|
|
62
|
-
// Reset lastElementMarginBottom before processing
|
|
63
|
-
_lastElementMarginBottom = 0.0;
|
|
64
|
-
[self removeTrailingSpacing:output];
|
|
65
|
-
|
|
66
|
-
// 4. Let the decorator post-process the finished string (e.g. stamp the quote's line height).
|
|
67
|
-
[block postProcess:output];
|
|
68
|
-
ENRMLinkPillsAdoptPlaceholderFonts(output);
|
|
69
|
-
|
|
70
|
-
// 5. Cleanup global state to prevent side effects in subsequent renders.
|
|
71
|
-
[context clearBlockStyle];
|
|
72
|
-
|
|
73
|
-
return output;
|
|
74
|
-
}
|
|
75
|
-
|
|
76
|
-
/**
|
|
77
|
-
* Trims trailing newlines after the last rendered block, with special handling for code blocks.
|
|
78
|
-
*
|
|
79
|
-
* For non-code-block tail elements: deletes all trailing newlines after the last non-newline
|
|
80
|
-
* character and zeroes the last element's paragraph spacing so it doesn't render a margin past
|
|
81
|
-
* the content.
|
|
82
|
-
*
|
|
83
|
-
* For code blocks (`isLastBlockACodeBlock` == YES): keeps the bottom padding spacer in place
|
|
84
|
-
* AND preserves a single trailing newline immediately after it (typically the
|
|
85
|
-
* codeBlockMarginBottom spacer that CodeBlockRenderer already appended; if none exists, one is
|
|
86
|
-
* synthesized here). That extra newline matters because of an iOS layout quirk:
|
|
87
|
-
*
|
|
88
|
-
* - iOS treats the trailing `\n` of the storage as a paragraph terminator and reports the
|
|
89
|
-
* line fragment for the paragraph after it via `extraLineFragmentRect`.
|
|
90
|
-
* - `boundingRectForGlyphRange:` excludes that extra line, and the graphics-context clip
|
|
91
|
-
* passed to `drawBackgroundForGlyphRange:` is tiled to the laid-out content area (rounded
|
|
92
|
-
* up to 128pt boundaries) which also excludes it.
|
|
93
|
-
* - If the bottom padding spacer were the trailing `\n`, its 16/19pt line fragment would
|
|
94
|
-
* fall into that excluded zone — the background rect would have to be manually extended
|
|
95
|
-
* past the clip and the bottom rounded corner would get sliced off at the tile boundary
|
|
96
|
-
* (the original visual bug in #354).
|
|
97
|
-
*
|
|
98
|
-
* By keeping a 1pt-tall tail newline beyond the bottom padding spacer, iOS lays the spacer
|
|
99
|
-
* out as a normal interior line fragment included in usedRect/boundingRect and inside the
|
|
100
|
-
* drawing tiles, so the corner renders intact and no rect extension is needed.
|
|
101
|
-
*/
|
|
102
|
-
- (void)removeTrailingSpacing:(NSMutableAttributedString *)output
|
|
103
|
-
{
|
|
104
|
-
if (output.length == 0)
|
|
105
|
-
return;
|
|
106
|
-
|
|
107
|
-
// Find the last non-newline character
|
|
108
|
-
NSRange lastContent = [output.string rangeOfCharacterFromSet:[NSCharacterSet.newlineCharacterSet invertedSet]
|
|
109
|
-
options:NSBackwardsSearch];
|
|
110
|
-
if (lastContent.location == NSNotFound)
|
|
111
|
-
return;
|
|
112
|
-
|
|
113
|
-
// 1. Capture the Margin Bottom (Scanning from last content to end)
|
|
114
|
-
_lastElementMarginBottom = 0.0;
|
|
115
|
-
for (NSUInteger i = lastContent.location; i < output.length;) {
|
|
116
|
-
NSRange attrRange;
|
|
117
|
-
NSParagraphStyle *style = [output attribute:NSParagraphStyleAttributeName atIndex:i effectiveRange:&attrRange];
|
|
118
|
-
if (style) {
|
|
119
|
-
_lastElementMarginBottom = MAX(_lastElementMarginBottom, style.paragraphSpacing);
|
|
120
|
-
}
|
|
121
|
-
i = NSMaxRange(attrRange);
|
|
122
|
-
}
|
|
123
|
-
|
|
124
|
-
// 2. Trim trailing characters
|
|
125
|
-
NSUInteger logicalEnd = NSMaxRange(lastContent);
|
|
126
|
-
BOOL isCodeBlock = isLastBlockACodeBlock(output);
|
|
127
|
-
BOOL isPaddedBlockquote = !isCodeBlock && [_config blockquotePadding] > 0 &&
|
|
128
|
-
[output attribute:BlockquoteDepthAttributeName
|
|
129
|
-
atIndex:lastContent.location
|
|
130
|
-
effectiveRange:NULL] != nil;
|
|
131
|
-
NSRange codeRange = NSMakeRange(0, 0);
|
|
132
|
-
if (isCodeBlock) {
|
|
133
|
-
[output attribute:CodeBlockAttributeName
|
|
134
|
-
atIndex:lastContent.location
|
|
135
|
-
longestEffectiveRange:&codeRange
|
|
136
|
-
inRange:NSMakeRange(0, output.length)];
|
|
137
|
-
NSUInteger codeEnd = NSMaxRange(codeRange);
|
|
138
|
-
if (codeEnd >= output.length) {
|
|
139
|
-
[output appendAttributedString:kNewlineAttributedString];
|
|
140
|
-
}
|
|
141
|
-
logicalEnd = codeEnd + 1;
|
|
142
|
-
} else if (isPaddedBlockquote) {
|
|
143
|
-
NSUInteger blockquoteEnd = NSMaxRange(lastContent);
|
|
144
|
-
while (blockquoteEnd < output.length && [output attribute:BlockquoteDepthAttributeName
|
|
145
|
-
atIndex:blockquoteEnd
|
|
146
|
-
effectiveRange:NULL] != nil) {
|
|
147
|
-
blockquoteEnd++;
|
|
148
|
-
}
|
|
149
|
-
if (blockquoteEnd >= output.length) {
|
|
150
|
-
[output appendAttributedString:kNewlineAttributedString];
|
|
151
|
-
}
|
|
152
|
-
logicalEnd = blockquoteEnd + 1;
|
|
153
|
-
}
|
|
154
|
-
|
|
155
|
-
if (logicalEnd < output.length) {
|
|
156
|
-
[output deleteCharactersInRange:NSMakeRange(logicalEnd, output.length - logicalEnd)];
|
|
157
|
-
}
|
|
158
|
-
|
|
159
|
-
if ((isCodeBlock && NSMaxRange(codeRange) < output.length) || isPaddedBlockquote) {
|
|
160
|
-
NSUInteger tailIdx = isCodeBlock ? NSMaxRange(codeRange) : logicalEnd - 1;
|
|
161
|
-
[output removeAttribute:CodeBlockAttributeName range:NSMakeRange(tailIdx, 1)];
|
|
162
|
-
[output removeAttribute:BlockquoteDepthAttributeName range:NSMakeRange(tailIdx, 1)];
|
|
163
|
-
[output removeAttribute:BlockquoteBackgroundColorAttributeName range:NSMakeRange(tailIdx, 1)];
|
|
164
|
-
NSParagraphStyle *style = [output attribute:NSParagraphStyleAttributeName atIndex:tailIdx effectiveRange:NULL];
|
|
165
|
-
NSMutableParagraphStyle *mutableStyle = style ? [style mutableCopy] : [[NSMutableParagraphStyle alloc] init];
|
|
166
|
-
mutableStyle.paragraphSpacing = 0;
|
|
167
|
-
mutableStyle.paragraphSpacingBefore = 0;
|
|
168
|
-
mutableStyle.minimumLineHeight = 1;
|
|
169
|
-
mutableStyle.maximumLineHeight = 1;
|
|
170
|
-
[output addAttribute:NSParagraphStyleAttributeName value:mutableStyle range:NSMakeRange(tailIdx, 1)];
|
|
171
|
-
}
|
|
172
|
-
|
|
173
|
-
// 3. Zero out internal spacing for the last element (if not a code block)
|
|
174
|
-
if (!isCodeBlock) {
|
|
175
|
-
NSRange styleRange;
|
|
176
|
-
NSParagraphStyle *style = [output attribute:NSParagraphStyleAttributeName
|
|
177
|
-
atIndex:lastContent.location
|
|
178
|
-
effectiveRange:&styleRange];
|
|
179
|
-
|
|
180
|
-
if (style) {
|
|
181
|
-
NSMutableParagraphStyle *mutableStyle = [style mutableCopy];
|
|
182
|
-
mutableStyle.paragraphSpacing = 0;
|
|
183
|
-
mutableStyle.paragraphSpacingBefore = 0;
|
|
184
|
-
|
|
185
|
-
if (isLastElementImage(output)) {
|
|
186
|
-
mutableStyle.lineSpacing = 0;
|
|
187
|
-
}
|
|
188
|
-
|
|
189
|
-
NSRange safeRange = NSIntersectionRange(styleRange, NSMakeRange(0, output.length));
|
|
190
|
-
[output addAttribute:NSParagraphStyleAttributeName value:mutableStyle range:safeRange];
|
|
191
|
-
}
|
|
192
|
-
}
|
|
193
|
-
}
|
|
194
|
-
|
|
195
|
-
- (void)setAllowTrailingMargin:(BOOL)allow
|
|
196
|
-
{
|
|
197
|
-
_allowTrailingMargin = allow;
|
|
198
|
-
}
|
|
199
|
-
|
|
200
|
-
- (CGFloat)getLastElementMarginBottom
|
|
201
|
-
{
|
|
202
|
-
return _lastElementMarginBottom;
|
|
203
|
-
}
|
|
204
|
-
|
|
205
|
-
/**
|
|
206
|
-
* Orchestrates the recursive traversal of the AST.
|
|
207
|
-
* If a specialized renderer exists for a node type, it takes full control.
|
|
208
|
-
*/
|
|
209
|
-
- (void)renderNodeRecursive:(TiptapASTNode *)node
|
|
210
|
-
into:(NSMutableAttributedString *)out
|
|
211
|
-
context:(RenderContext *)context
|
|
212
|
-
{
|
|
213
|
-
if (!node)
|
|
214
|
-
return;
|
|
215
|
-
|
|
216
|
-
id<NodeRenderer> renderer = [_rendererFactory rendererForNodeType:node.type];
|
|
217
|
-
|
|
218
|
-
if (renderer) {
|
|
219
|
-
// Specialized renderers (e.g., Strong, Link, Heading) handle their own sub-trees.
|
|
220
|
-
[renderer renderNode:node into:out context:context];
|
|
221
|
-
} else {
|
|
222
|
-
// Fallback: Default to deep-first traversal for unhandled container nodes.
|
|
223
|
-
for (TiptapASTNode *child in node.children) {
|
|
224
|
-
[self renderNodeRecursive:child into:out context:context];
|
|
225
|
-
}
|
|
226
|
-
}
|
|
227
|
-
}
|
|
228
|
-
|
|
229
|
-
@end
|
|
1
|
+
#import "AttributedRenderer.h"
|
|
2
|
+
#import "BlockquoteBorder.h"
|
|
3
|
+
#import "CodeBlockBackground.h"
|
|
4
|
+
#import "ENRMBlockquoteTextRenderer.h"
|
|
5
|
+
#import "ENRMLinkPillText.h"
|
|
6
|
+
#import "LastElementUtils.h"
|
|
7
|
+
#import "TiptapASTNode.h"
|
|
8
|
+
#import "NodeRenderer.h"
|
|
9
|
+
#import "ParagraphStyleUtils.h"
|
|
10
|
+
#import "RenderContext.h"
|
|
11
|
+
#import "RendererFactory.h"
|
|
12
|
+
#import "StyleConfig.h"
|
|
13
|
+
|
|
14
|
+
@implementation AttributedRenderer {
|
|
15
|
+
StyleConfig *_config;
|
|
16
|
+
RendererFactory *_rendererFactory;
|
|
17
|
+
CGFloat _lastElementMarginBottom;
|
|
18
|
+
BOOL _allowTrailingMargin;
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
- (instancetype)initWithConfig:(StyleConfig *)config
|
|
22
|
+
{
|
|
23
|
+
self = [super init];
|
|
24
|
+
if (self) {
|
|
25
|
+
_config = config;
|
|
26
|
+
_rendererFactory = [[RendererFactory alloc] initWithConfig:config];
|
|
27
|
+
_lastElementMarginBottom = 0.0;
|
|
28
|
+
_allowTrailingMargin = NO;
|
|
29
|
+
}
|
|
30
|
+
return self;
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
/**
|
|
34
|
+
* Entry point for rendering a flat list of sibling nodes (e.g. a document's or a block segment's
|
|
35
|
+
* children). Sets the baseline block style, runs the recursive traversal, and trims the trailing
|
|
36
|
+
* block margin. An optional [block] decorates the pass - it enters a block baseline before the nodes
|
|
37
|
+
* render and post-processes the finished string - letting a caller render content as e.g. blockquote
|
|
38
|
+
* text without this class knowing anything block-specific. See ENRMBlockquoteTextRenderer.
|
|
39
|
+
*/
|
|
40
|
+
- (NSMutableAttributedString *)renderNodes:(NSArray<TiptapASTNode *> *)nodes
|
|
41
|
+
context:(RenderContext *)context
|
|
42
|
+
block:(ENRMBlockquoteTextRenderer *)block
|
|
43
|
+
{
|
|
44
|
+
// 1. Establish the baseline block style. This ensures leaf nodes (like Text) have valid
|
|
45
|
+
// attributes if they appear at the top level. A decorator overrides the default paragraph
|
|
46
|
+
// baseline (e.g. the blockquote baseline so paragraphs render tight and pick up the quote's
|
|
47
|
+
// font/color).
|
|
48
|
+
if (block) {
|
|
49
|
+
[block pushOnContext:context];
|
|
50
|
+
} else {
|
|
51
|
+
[context setBlockStyle:BlockTypeParagraph font:_config.paragraphFont color:_config.paragraphColor headingLevel:0];
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
NSMutableAttributedString *output = [[NSMutableAttributedString alloc] init];
|
|
55
|
+
|
|
56
|
+
// 2. Iterate through the sibling nodes.
|
|
57
|
+
for (TiptapASTNode *node in nodes) {
|
|
58
|
+
[self renderNodeRecursive:node into:output context:context];
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
// 3. Remove trailing paragraph spacing from last block element
|
|
62
|
+
// Reset lastElementMarginBottom before processing
|
|
63
|
+
_lastElementMarginBottom = 0.0;
|
|
64
|
+
[self removeTrailingSpacing:output];
|
|
65
|
+
|
|
66
|
+
// 4. Let the decorator post-process the finished string (e.g. stamp the quote's line height).
|
|
67
|
+
[block postProcess:output];
|
|
68
|
+
ENRMLinkPillsAdoptPlaceholderFonts(output);
|
|
69
|
+
|
|
70
|
+
// 5. Cleanup global state to prevent side effects in subsequent renders.
|
|
71
|
+
[context clearBlockStyle];
|
|
72
|
+
|
|
73
|
+
return output;
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
/**
|
|
77
|
+
* Trims trailing newlines after the last rendered block, with special handling for code blocks.
|
|
78
|
+
*
|
|
79
|
+
* For non-code-block tail elements: deletes all trailing newlines after the last non-newline
|
|
80
|
+
* character and zeroes the last element's paragraph spacing so it doesn't render a margin past
|
|
81
|
+
* the content.
|
|
82
|
+
*
|
|
83
|
+
* For code blocks (`isLastBlockACodeBlock` == YES): keeps the bottom padding spacer in place
|
|
84
|
+
* AND preserves a single trailing newline immediately after it (typically the
|
|
85
|
+
* codeBlockMarginBottom spacer that CodeBlockRenderer already appended; if none exists, one is
|
|
86
|
+
* synthesized here). That extra newline matters because of an iOS layout quirk:
|
|
87
|
+
*
|
|
88
|
+
* - iOS treats the trailing `\n` of the storage as a paragraph terminator and reports the
|
|
89
|
+
* line fragment for the paragraph after it via `extraLineFragmentRect`.
|
|
90
|
+
* - `boundingRectForGlyphRange:` excludes that extra line, and the graphics-context clip
|
|
91
|
+
* passed to `drawBackgroundForGlyphRange:` is tiled to the laid-out content area (rounded
|
|
92
|
+
* up to 128pt boundaries) which also excludes it.
|
|
93
|
+
* - If the bottom padding spacer were the trailing `\n`, its 16/19pt line fragment would
|
|
94
|
+
* fall into that excluded zone — the background rect would have to be manually extended
|
|
95
|
+
* past the clip and the bottom rounded corner would get sliced off at the tile boundary
|
|
96
|
+
* (the original visual bug in #354).
|
|
97
|
+
*
|
|
98
|
+
* By keeping a 1pt-tall tail newline beyond the bottom padding spacer, iOS lays the spacer
|
|
99
|
+
* out as a normal interior line fragment included in usedRect/boundingRect and inside the
|
|
100
|
+
* drawing tiles, so the corner renders intact and no rect extension is needed.
|
|
101
|
+
*/
|
|
102
|
+
- (void)removeTrailingSpacing:(NSMutableAttributedString *)output
|
|
103
|
+
{
|
|
104
|
+
if (output.length == 0)
|
|
105
|
+
return;
|
|
106
|
+
|
|
107
|
+
// Find the last non-newline character
|
|
108
|
+
NSRange lastContent = [output.string rangeOfCharacterFromSet:[NSCharacterSet.newlineCharacterSet invertedSet]
|
|
109
|
+
options:NSBackwardsSearch];
|
|
110
|
+
if (lastContent.location == NSNotFound)
|
|
111
|
+
return;
|
|
112
|
+
|
|
113
|
+
// 1. Capture the Margin Bottom (Scanning from last content to end)
|
|
114
|
+
_lastElementMarginBottom = 0.0;
|
|
115
|
+
for (NSUInteger i = lastContent.location; i < output.length;) {
|
|
116
|
+
NSRange attrRange;
|
|
117
|
+
NSParagraphStyle *style = [output attribute:NSParagraphStyleAttributeName atIndex:i effectiveRange:&attrRange];
|
|
118
|
+
if (style) {
|
|
119
|
+
_lastElementMarginBottom = MAX(_lastElementMarginBottom, style.paragraphSpacing);
|
|
120
|
+
}
|
|
121
|
+
i = NSMaxRange(attrRange);
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
// 2. Trim trailing characters
|
|
125
|
+
NSUInteger logicalEnd = NSMaxRange(lastContent);
|
|
126
|
+
BOOL isCodeBlock = isLastBlockACodeBlock(output);
|
|
127
|
+
BOOL isPaddedBlockquote = !isCodeBlock && [_config blockquotePadding] > 0 &&
|
|
128
|
+
[output attribute:BlockquoteDepthAttributeName
|
|
129
|
+
atIndex:lastContent.location
|
|
130
|
+
effectiveRange:NULL] != nil;
|
|
131
|
+
NSRange codeRange = NSMakeRange(0, 0);
|
|
132
|
+
if (isCodeBlock) {
|
|
133
|
+
[output attribute:CodeBlockAttributeName
|
|
134
|
+
atIndex:lastContent.location
|
|
135
|
+
longestEffectiveRange:&codeRange
|
|
136
|
+
inRange:NSMakeRange(0, output.length)];
|
|
137
|
+
NSUInteger codeEnd = NSMaxRange(codeRange);
|
|
138
|
+
if (codeEnd >= output.length) {
|
|
139
|
+
[output appendAttributedString:kNewlineAttributedString];
|
|
140
|
+
}
|
|
141
|
+
logicalEnd = codeEnd + 1;
|
|
142
|
+
} else if (isPaddedBlockquote) {
|
|
143
|
+
NSUInteger blockquoteEnd = NSMaxRange(lastContent);
|
|
144
|
+
while (blockquoteEnd < output.length && [output attribute:BlockquoteDepthAttributeName
|
|
145
|
+
atIndex:blockquoteEnd
|
|
146
|
+
effectiveRange:NULL] != nil) {
|
|
147
|
+
blockquoteEnd++;
|
|
148
|
+
}
|
|
149
|
+
if (blockquoteEnd >= output.length) {
|
|
150
|
+
[output appendAttributedString:kNewlineAttributedString];
|
|
151
|
+
}
|
|
152
|
+
logicalEnd = blockquoteEnd + 1;
|
|
153
|
+
}
|
|
154
|
+
|
|
155
|
+
if (logicalEnd < output.length) {
|
|
156
|
+
[output deleteCharactersInRange:NSMakeRange(logicalEnd, output.length - logicalEnd)];
|
|
157
|
+
}
|
|
158
|
+
|
|
159
|
+
if ((isCodeBlock && NSMaxRange(codeRange) < output.length) || isPaddedBlockquote) {
|
|
160
|
+
NSUInteger tailIdx = isCodeBlock ? NSMaxRange(codeRange) : logicalEnd - 1;
|
|
161
|
+
[output removeAttribute:CodeBlockAttributeName range:NSMakeRange(tailIdx, 1)];
|
|
162
|
+
[output removeAttribute:BlockquoteDepthAttributeName range:NSMakeRange(tailIdx, 1)];
|
|
163
|
+
[output removeAttribute:BlockquoteBackgroundColorAttributeName range:NSMakeRange(tailIdx, 1)];
|
|
164
|
+
NSParagraphStyle *style = [output attribute:NSParagraphStyleAttributeName atIndex:tailIdx effectiveRange:NULL];
|
|
165
|
+
NSMutableParagraphStyle *mutableStyle = style ? [style mutableCopy] : [[NSMutableParagraphStyle alloc] init];
|
|
166
|
+
mutableStyle.paragraphSpacing = 0;
|
|
167
|
+
mutableStyle.paragraphSpacingBefore = 0;
|
|
168
|
+
mutableStyle.minimumLineHeight = 1;
|
|
169
|
+
mutableStyle.maximumLineHeight = 1;
|
|
170
|
+
[output addAttribute:NSParagraphStyleAttributeName value:mutableStyle range:NSMakeRange(tailIdx, 1)];
|
|
171
|
+
}
|
|
172
|
+
|
|
173
|
+
// 3. Zero out internal spacing for the last element (if not a code block)
|
|
174
|
+
if (!isCodeBlock) {
|
|
175
|
+
NSRange styleRange;
|
|
176
|
+
NSParagraphStyle *style = [output attribute:NSParagraphStyleAttributeName
|
|
177
|
+
atIndex:lastContent.location
|
|
178
|
+
effectiveRange:&styleRange];
|
|
179
|
+
|
|
180
|
+
if (style) {
|
|
181
|
+
NSMutableParagraphStyle *mutableStyle = [style mutableCopy];
|
|
182
|
+
mutableStyle.paragraphSpacing = 0;
|
|
183
|
+
mutableStyle.paragraphSpacingBefore = 0;
|
|
184
|
+
|
|
185
|
+
if (isLastElementImage(output)) {
|
|
186
|
+
mutableStyle.lineSpacing = 0;
|
|
187
|
+
}
|
|
188
|
+
|
|
189
|
+
NSRange safeRange = NSIntersectionRange(styleRange, NSMakeRange(0, output.length));
|
|
190
|
+
[output addAttribute:NSParagraphStyleAttributeName value:mutableStyle range:safeRange];
|
|
191
|
+
}
|
|
192
|
+
}
|
|
193
|
+
}
|
|
194
|
+
|
|
195
|
+
- (void)setAllowTrailingMargin:(BOOL)allow
|
|
196
|
+
{
|
|
197
|
+
_allowTrailingMargin = allow;
|
|
198
|
+
}
|
|
199
|
+
|
|
200
|
+
- (CGFloat)getLastElementMarginBottom
|
|
201
|
+
{
|
|
202
|
+
return _lastElementMarginBottom;
|
|
203
|
+
}
|
|
204
|
+
|
|
205
|
+
/**
|
|
206
|
+
* Orchestrates the recursive traversal of the AST.
|
|
207
|
+
* If a specialized renderer exists for a node type, it takes full control.
|
|
208
|
+
*/
|
|
209
|
+
- (void)renderNodeRecursive:(TiptapASTNode *)node
|
|
210
|
+
into:(NSMutableAttributedString *)out
|
|
211
|
+
context:(RenderContext *)context
|
|
212
|
+
{
|
|
213
|
+
if (!node)
|
|
214
|
+
return;
|
|
215
|
+
|
|
216
|
+
id<NodeRenderer> renderer = [_rendererFactory rendererForNodeType:node.type];
|
|
217
|
+
|
|
218
|
+
if (renderer) {
|
|
219
|
+
// Specialized renderers (e.g., Strong, Link, Heading) handle their own sub-trees.
|
|
220
|
+
[renderer renderNode:node into:out context:context];
|
|
221
|
+
} else {
|
|
222
|
+
// Fallback: Default to deep-first traversal for unhandled container nodes.
|
|
223
|
+
for (TiptapASTNode *child in node.children) {
|
|
224
|
+
[self renderNodeRecursive:child into:out context:context];
|
|
225
|
+
}
|
|
226
|
+
}
|
|
227
|
+
}
|
|
228
|
+
|
|
229
|
+
@end
|
|
@@ -1,33 +1,33 @@
|
|
|
1
|
-
#pragma once
|
|
2
|
-
#import "NodeRenderer.h"
|
|
3
|
-
|
|
4
|
-
@class RendererFactory;
|
|
5
|
-
@class StyleConfig;
|
|
6
|
-
@class RenderContext;
|
|
7
|
-
@class TiptapASTNode;
|
|
8
|
-
|
|
9
|
-
/// Shared base for all node renderers — provides `_rendererFactory` and `_config`
|
|
10
|
-
/// as protected ivars and the common designated initializer.
|
|
11
|
-
/// `renderNode:into:context:` is a template method: take context snapshot ->
|
|
12
|
-
/// `renderNodeContent:into:context:` -> restore snapshot. Subclasses implement
|
|
13
|
-
/// `renderNodeContent:into:context:` and, when they mutate scoped context state,
|
|
14
|
-
/// override `takeContextSnapshot:` to return `[context snapshotScope]`.
|
|
15
|
-
@interface BaseRenderer : NSObject <NodeRenderer> {
|
|
16
|
-
@protected
|
|
17
|
-
__weak RendererFactory *_rendererFactory;
|
|
18
|
-
StyleConfig *_config;
|
|
19
|
-
}
|
|
20
|
-
|
|
21
|
-
- (instancetype)initWithRendererFactory:(id)rendererFactory config:(id)config;
|
|
22
|
-
|
|
23
|
-
- (void)renderNodeContent:(TiptapASTNode *)node
|
|
24
|
-
into:(NSMutableAttributedString *)output
|
|
25
|
-
context:(RenderContext *)context;
|
|
26
|
-
|
|
27
|
-
/// Default returns nil.
|
|
28
|
-
- (nullable id)takeContextSnapshot:(RenderContext *)context;
|
|
29
|
-
|
|
30
|
-
/// Default restores a scope frame when snapshot is non-nil, no-op otherwise.
|
|
31
|
-
- (void)restoreContextSnapshot:(nullable id)snapshot context:(RenderContext *)context;
|
|
32
|
-
|
|
33
|
-
@end
|
|
1
|
+
#pragma once
|
|
2
|
+
#import "NodeRenderer.h"
|
|
3
|
+
|
|
4
|
+
@class RendererFactory;
|
|
5
|
+
@class StyleConfig;
|
|
6
|
+
@class RenderContext;
|
|
7
|
+
@class TiptapASTNode;
|
|
8
|
+
|
|
9
|
+
/// Shared base for all node renderers — provides `_rendererFactory` and `_config`
|
|
10
|
+
/// as protected ivars and the common designated initializer.
|
|
11
|
+
/// `renderNode:into:context:` is a template method: take context snapshot ->
|
|
12
|
+
/// `renderNodeContent:into:context:` -> restore snapshot. Subclasses implement
|
|
13
|
+
/// `renderNodeContent:into:context:` and, when they mutate scoped context state,
|
|
14
|
+
/// override `takeContextSnapshot:` to return `[context snapshotScope]`.
|
|
15
|
+
@interface BaseRenderer : NSObject <NodeRenderer> {
|
|
16
|
+
@protected
|
|
17
|
+
__weak RendererFactory *_rendererFactory;
|
|
18
|
+
StyleConfig *_config;
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
- (instancetype)initWithRendererFactory:(id)rendererFactory config:(id)config;
|
|
22
|
+
|
|
23
|
+
- (void)renderNodeContent:(TiptapASTNode *)node
|
|
24
|
+
into:(NSMutableAttributedString *)output
|
|
25
|
+
context:(RenderContext *)context;
|
|
26
|
+
|
|
27
|
+
/// Default returns nil.
|
|
28
|
+
- (nullable id)takeContextSnapshot:(RenderContext *)context;
|
|
29
|
+
|
|
30
|
+
/// Default restores a scope frame when snapshot is non-nil, no-op otherwise.
|
|
31
|
+
- (void)restoreContextSnapshot:(nullable id)snapshot context:(RenderContext *)context;
|
|
32
|
+
|
|
33
|
+
@end
|