@mathers101/react-native-render-rich-text 0.0.0-stage → 0.1.9
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +20 -0
- package/README.md +140 -3
- package/ReactNativeRenderRichText.podspec +23 -0
- package/android/build.gradle +86 -0
- package/android/consumer-rules.pro +3 -0
- package/android/src/main/AndroidManifest.xml +2 -0
- package/android/src/main/cpp/jni-adapter.cpp +191 -0
- package/android/src/main/java/com/renderrichtext/EnrichedTiptapText.kt +673 -0
- package/android/src/main/java/com/renderrichtext/EnrichedTiptapTextLayoutManager.kt +24 -0
- package/android/src/main/java/com/renderrichtext/EnrichedTiptapTextManager.kt +405 -0
- package/android/src/main/java/com/renderrichtext/EnrichedTiptapTextPackage.kt +13 -0
- package/android/src/main/java/com/renderrichtext/MeasurementStore.kt +644 -0
- package/android/src/main/java/com/renderrichtext/accessibility/AccessibilityLabels.kt +17 -0
- package/android/src/main/java/com/renderrichtext/accessibility/AccessibleTiptapTextView.kt +112 -0
- package/android/src/main/java/com/renderrichtext/accessibility/TiptapAccessibilityHelper.kt +576 -0
- package/android/src/main/java/com/renderrichtext/events/CodeBlockPressEvent.kt +24 -0
- package/android/src/main/java/com/renderrichtext/events/ContextMenuItemPressEvent.kt +28 -0
- package/android/src/main/java/com/renderrichtext/events/CopyPressEvent.kt +24 -0
- package/android/src/main/java/com/renderrichtext/events/FactoidPressEvent.kt +23 -0
- package/android/src/main/java/com/renderrichtext/events/ImagePressEvent.kt +25 -0
- package/android/src/main/java/com/renderrichtext/events/LatexErrorEvent.kt +29 -0
- package/android/src/main/java/com/renderrichtext/events/LinkLongPressEvent.kt +23 -0
- package/android/src/main/java/com/renderrichtext/events/LinkPressEvent.kt +23 -0
- package/android/src/main/java/com/renderrichtext/events/MentionLongPressEvent.kt +25 -0
- package/android/src/main/java/com/renderrichtext/events/MentionPressEvent.kt +25 -0
- package/android/src/main/java/com/renderrichtext/events/TaskListItemPressEvent.kt +26 -0
- package/android/src/main/java/com/renderrichtext/math/LatexErrorReporter.kt +9 -0
- package/android/src/main/java/com/renderrichtext/parser/Parser.kt +59 -0
- package/android/src/main/java/com/renderrichtext/parser/TextLinkMatching.kt +35 -0
- package/android/src/main/java/com/renderrichtext/parser/TiptapASTNode.kt +69 -0
- package/android/src/main/java/com/renderrichtext/renderer/BaselineShiftRenderer.kt +45 -0
- package/android/src/main/java/com/renderrichtext/renderer/BlankLineRenderer.kt +39 -0
- package/android/src/main/java/com/renderrichtext/renderer/BlockStyleContext.kt +181 -0
- package/android/src/main/java/com/renderrichtext/renderer/BlockquoteRenderer.kt +243 -0
- package/android/src/main/java/com/renderrichtext/renderer/BlockquoteTextRenderer.kt +56 -0
- package/android/src/main/java/com/renderrichtext/renderer/CodeBlockRenderer.kt +135 -0
- package/android/src/main/java/com/renderrichtext/renderer/CodeRenderer.kt +37 -0
- package/android/src/main/java/com/renderrichtext/renderer/EmphasisRenderer.kt +28 -0
- package/android/src/main/java/com/renderrichtext/renderer/FactoidRenderer.kt +97 -0
- package/android/src/main/java/com/renderrichtext/renderer/HeadingRenderer.kt +81 -0
- package/android/src/main/java/com/renderrichtext/renderer/HighlightRenderer.kt +26 -0
- package/android/src/main/java/com/renderrichtext/renderer/LineBreakRenderer.kt +17 -0
- package/android/src/main/java/com/renderrichtext/renderer/LinkRenderer.kt +90 -0
- package/android/src/main/java/com/renderrichtext/renderer/ListContextManager.kt +109 -0
- package/android/src/main/java/com/renderrichtext/renderer/ListItemRenderer.kt +211 -0
- package/android/src/main/java/com/renderrichtext/renderer/ListRenderer.kt +133 -0
- package/android/src/main/java/com/renderrichtext/renderer/MentionRenderer.kt +85 -0
- package/android/src/main/java/com/renderrichtext/renderer/NodeRenderer.kt +207 -0
- package/android/src/main/java/com/renderrichtext/renderer/ParagraphRenderer.kt +91 -0
- package/android/src/main/java/com/renderrichtext/renderer/Renderer.kt +148 -0
- package/android/src/main/java/com/renderrichtext/renderer/SoftBreakRenderer.kt +17 -0
- package/android/src/main/java/com/renderrichtext/renderer/SpanStyleCache.kt +143 -0
- package/android/src/main/java/com/renderrichtext/renderer/StrikethroughRenderer.kt +28 -0
- package/android/src/main/java/com/renderrichtext/renderer/StrongRenderer.kt +28 -0
- package/android/src/main/java/com/renderrichtext/renderer/TextRenderer.kt +31 -0
- package/android/src/main/java/com/renderrichtext/renderer/ThematicBreakRenderer.kt +46 -0
- package/android/src/main/java/com/renderrichtext/renderer/UnderlineRenderer.kt +28 -0
- package/android/src/main/java/com/renderrichtext/spans/BaseListSpan.kt +164 -0
- package/android/src/main/java/com/renderrichtext/spans/BaselineShiftSpan.kt +27 -0
- package/android/src/main/java/com/renderrichtext/spans/BlockquoteSpan.kt +302 -0
- package/android/src/main/java/com/renderrichtext/spans/CodeBackgroundSpan.kt +205 -0
- package/android/src/main/java/com/renderrichtext/spans/CodeBlockSpan.kt +216 -0
- package/android/src/main/java/com/renderrichtext/spans/CodeSpan.kt +32 -0
- package/android/src/main/java/com/renderrichtext/spans/EmphasisSpan.kt +42 -0
- package/android/src/main/java/com/renderrichtext/spans/FactoidBackgroundSpan.kt +265 -0
- package/android/src/main/java/com/renderrichtext/spans/FactoidPaddingSpan.kt +258 -0
- package/android/src/main/java/com/renderrichtext/spans/FactoidSpan.kt +32 -0
- package/android/src/main/java/com/renderrichtext/spans/FadeInSpan.kt +29 -0
- package/android/src/main/java/com/renderrichtext/spans/HeadingSpan.kt +38 -0
- package/android/src/main/java/com/renderrichtext/spans/HighlightSpan.kt +80 -0
- package/android/src/main/java/com/renderrichtext/spans/ImageSpan.kt +481 -0
- package/android/src/main/java/com/renderrichtext/spans/InlineBackgroundGeometry.kt +42 -0
- package/android/src/main/java/com/renderrichtext/spans/LineHeightSpan.kt +39 -0
- package/android/src/main/java/com/renderrichtext/spans/LinkPillIconCache.kt +154 -0
- package/android/src/main/java/com/renderrichtext/spans/LinkPillSpan.kt +381 -0
- package/android/src/main/java/com/renderrichtext/spans/LinkSpan.kt +68 -0
- package/android/src/main/java/com/renderrichtext/spans/ListItemSpacingSpan.kt +33 -0
- package/android/src/main/java/com/renderrichtext/spans/ListMarkerAnchorSpan.kt +38 -0
- package/android/src/main/java/com/renderrichtext/spans/MarginBottomSpan.kt +76 -0
- package/android/src/main/java/com/renderrichtext/spans/MentionChipSpan.kt +132 -0
- package/android/src/main/java/com/renderrichtext/spans/MentionSpan.kt +46 -0
- package/android/src/main/java/com/renderrichtext/spans/OrderedListSpan.kt +127 -0
- package/android/src/main/java/com/renderrichtext/spans/SpoilerSpan.kt +33 -0
- package/android/src/main/java/com/renderrichtext/spans/StrikethroughSpan.kt +12 -0
- package/android/src/main/java/com/renderrichtext/spans/StrongSpan.kt +39 -0
- package/android/src/main/java/com/renderrichtext/spans/TaskListSpan.kt +143 -0
- package/android/src/main/java/com/renderrichtext/spans/TextSpan.kt +26 -0
- package/android/src/main/java/com/renderrichtext/spans/ThematicBreakSpan.kt +69 -0
- package/android/src/main/java/com/renderrichtext/spans/UnorderedListSpan.kt +96 -0
- package/android/src/main/java/com/renderrichtext/spoiler/SpoilerStubs.kt +46 -0
- package/android/src/main/java/com/renderrichtext/styles/BaseBlockStyle.kt +11 -0
- package/android/src/main/java/com/renderrichtext/styles/BlockquoteStyle.kt +83 -0
- package/android/src/main/java/com/renderrichtext/styles/CodeBlockStyle.kt +80 -0
- package/android/src/main/java/com/renderrichtext/styles/CodeStyle.kt +26 -0
- package/android/src/main/java/com/renderrichtext/styles/EmphasisStyle.kt +21 -0
- package/android/src/main/java/com/renderrichtext/styles/FactoidStyle.kt +21 -0
- package/android/src/main/java/com/renderrichtext/styles/HeadingStyle.kt +33 -0
- package/android/src/main/java/com/renderrichtext/styles/HighlightStyle.kt +19 -0
- package/android/src/main/java/com/renderrichtext/styles/ImageStyle.kt +29 -0
- package/android/src/main/java/com/renderrichtext/styles/InlineImageStyle.kt +17 -0
- package/android/src/main/java/com/renderrichtext/styles/InlineMathStyle.kt +17 -0
- package/android/src/main/java/com/renderrichtext/styles/LinkPillContent.kt +36 -0
- package/android/src/main/java/com/renderrichtext/styles/LinkPillStyle.kt +44 -0
- package/android/src/main/java/com/renderrichtext/styles/LinkStyle.kt +23 -0
- package/android/src/main/java/com/renderrichtext/styles/LinkVariantEntry.kt +34 -0
- package/android/src/main/java/com/renderrichtext/styles/ListStyle.kt +65 -0
- package/android/src/main/java/com/renderrichtext/styles/MathStyle.kt +29 -0
- package/android/src/main/java/com/renderrichtext/styles/MentionStyle.kt +19 -0
- package/android/src/main/java/com/renderrichtext/styles/ParagraphStyle.kt +33 -0
- package/android/src/main/java/com/renderrichtext/styles/SpoilerStyle.kt +27 -0
- package/android/src/main/java/com/renderrichtext/styles/StrikethroughStyle.kt +17 -0
- package/android/src/main/java/com/renderrichtext/styles/StrongStyle.kt +21 -0
- package/android/src/main/java/com/renderrichtext/styles/StyleConfig.kt +411 -0
- package/android/src/main/java/com/renderrichtext/styles/StyleParser.kt +92 -0
- package/android/src/main/java/com/renderrichtext/styles/SubscriptStyle.kt +16 -0
- package/android/src/main/java/com/renderrichtext/styles/SuperscriptStyle.kt +16 -0
- package/android/src/main/java/com/renderrichtext/styles/TableStyle.kt +75 -0
- package/android/src/main/java/com/renderrichtext/styles/TaskListStyle.kt +29 -0
- package/android/src/main/java/com/renderrichtext/styles/TextAlignment.kt +32 -0
- package/android/src/main/java/com/renderrichtext/styles/ThematicBreakStyle.kt +23 -0
- package/android/src/main/java/com/renderrichtext/styles/UnderlineStyle.kt +17 -0
- package/android/src/main/java/com/renderrichtext/styles/VideoStyle.kt +31 -0
- package/android/src/main/java/com/renderrichtext/utils/common/BorderStyleUtils.kt +86 -0
- package/android/src/main/java/com/renderrichtext/utils/common/BreakStrategyUtils.kt +32 -0
- package/android/src/main/java/com/renderrichtext/utils/common/CodeBlockHighlighter.kt +36 -0
- package/android/src/main/java/com/renderrichtext/utils/common/CodeBlockNode.kt +42 -0
- package/android/src/main/java/com/renderrichtext/utils/common/EllipsizeUtils.kt +27 -0
- package/android/src/main/java/com/renderrichtext/utils/common/EnrichedTiptapAncestorUtils.kt +10 -0
- package/android/src/main/java/com/renderrichtext/utils/common/FeatureFlags.kt +9 -0
- package/android/src/main/java/com/renderrichtext/utils/common/LinkRecognitionProps.kt +31 -0
- package/android/src/main/java/com/renderrichtext/utils/common/LinkRegexConfig.kt +56 -0
- package/android/src/main/java/com/renderrichtext/utils/common/MotionPreferences.kt +18 -0
- package/android/src/main/java/com/renderrichtext/utils/common/ReadableMapExtensions.kt +28 -0
- package/android/src/main/java/com/renderrichtext/utils/common/TiptapViewManagerUtils.kt +242 -0
- package/android/src/main/java/com/renderrichtext/utils/common/layout/RTLUtils.kt +6 -0
- package/android/src/main/java/com/renderrichtext/utils/common/serialization/TiptapASTSerializer.kt +368 -0
- package/android/src/main/java/com/renderrichtext/utils/text/ImageCache.kt +88 -0
- package/android/src/main/java/com/renderrichtext/utils/text/ImageDownloader.kt +203 -0
- package/android/src/main/java/com/renderrichtext/utils/text/LocalImageLoader.kt +167 -0
- package/android/src/main/java/com/renderrichtext/utils/text/TailFadeInAnimator.kt +84 -0
- package/android/src/main/java/com/renderrichtext/utils/text/conversion/HTMLGenerator.kt +1105 -0
- package/android/src/main/java/com/renderrichtext/utils/text/conversion/TiptapExtractor.kt +423 -0
- package/android/src/main/java/com/renderrichtext/utils/text/extensions/ParagraphUtils.kt +9 -0
- package/android/src/main/java/com/renderrichtext/utils/text/extensions/SpannableExtensions.kt +9 -0
- package/android/src/main/java/com/renderrichtext/utils/text/extensions/TextPaintExtensions.kt +76 -0
- package/android/src/main/java/com/renderrichtext/utils/text/interaction/CheckboxTouchHelper.kt +61 -0
- package/android/src/main/java/com/renderrichtext/utils/text/interaction/TaskListTapUtils.kt +286 -0
- package/android/src/main/java/com/renderrichtext/utils/text/span/ApplyLineHeight.kt +39 -0
- package/android/src/main/java/com/renderrichtext/utils/text/span/BlockSpacing.kt +142 -0
- package/android/src/main/java/com/renderrichtext/utils/text/span/SpanFlags.kt +43 -0
- package/android/src/main/java/com/renderrichtext/utils/text/span/WidthAwareSpans.kt +30 -0
- package/android/src/main/java/com/renderrichtext/utils/text/view/CodeBlockPressHost.kt +15 -0
- package/android/src/main/java/com/renderrichtext/utils/text/view/ImagePressHost.kt +19 -0
- package/android/src/main/java/com/renderrichtext/utils/text/view/LinkEvents.kt +88 -0
- package/android/src/main/java/com/renderrichtext/utils/text/view/LinkLongPressMovementMethod.kt +449 -0
- package/android/src/main/java/com/renderrichtext/utils/text/view/SelectionActionMode.kt +235 -0
- package/android/src/main/java/com/renderrichtext/utils/text/view/TextSelectionColors.kt +48 -0
- package/android/src/main/java/com/renderrichtext/utils/text/view/TextViewSetup.kt +119 -0
- package/android/src/main/java/com/renderrichtext/views/ContextMenuPopup.kt +217 -0
- package/android/src/main/java/com/renderrichtext/views/CopyGlyph.kt +101 -0
- package/android/src/main/java/com/renderrichtext/views/WrapGlyph.kt +40 -0
- package/android/src/main/jni/CMakeLists.txt +52 -0
- package/android/src/main/jni/react/renderer/components/RichTextSpec/ComponentDescriptors.h +30 -0
- package/android/src/main/jni/react/renderer/components/RichTextSpec/TiptapTextComponentDescriptor.h +29 -0
- package/android/src/main/jni/react/renderer/components/RichTextSpec/TiptapTextMeasurementManager.cpp +45 -0
- package/android/src/main/jni/react/renderer/components/RichTextSpec/TiptapTextMeasurementManager.h +21 -0
- package/android/src/main/jni/react/renderer/components/RichTextSpec/TiptapTextShadowNode.cpp +38 -0
- package/android/src/main/jni/react/renderer/components/RichTextSpec/TiptapTextShadowNode.h +53 -0
- package/android/src/main/jni/react/renderer/components/RichTextSpec/TiptapTextState.cpp +9 -0
- package/android/src/main/jni/react/renderer/components/RichTextSpec/TiptapTextState.h +24 -0
- package/android/src/main/jni/react/renderer/components/RichTextSpec/conversions.h +40 -0
- package/cpp/parser/TiptapASTNode.hpp +68 -0
- package/cpp/parser/TiptapParser.cpp +233 -0
- package/cpp/parser/TiptapParser.hpp +13 -0
- package/cpp/vendor/nlohmann/json.hpp +24765 -0
- package/ios/EnrichedTiptapText.h +27 -0
- package/ios/EnrichedTiptapText.mm +1222 -0
- package/ios/attachments/ENRMImageAttachment.h +51 -0
- package/ios/attachments/ENRMImageAttachment.m +398 -0
- package/ios/attachments/ENRMLinkPillAttachment.h +47 -0
- package/ios/attachments/ENRMLinkPillAttachment.m +324 -0
- package/ios/attachments/ENRMLinkPillIconCache.h +28 -0
- package/ios/attachments/ENRMLinkPillIconCache.m +181 -0
- package/ios/attachments/ENRMLinkPillText.h +27 -0
- package/ios/attachments/ENRMLinkPillText.m +118 -0
- package/ios/attachments/ENRMMathInlineAttachment.h +7 -0
- package/ios/attachments/ENRMMathInlineAttachment.m +4 -0
- package/ios/attachments/ThematicBreakAttachment.h +15 -0
- package/ios/attachments/ThematicBreakAttachment.m +33 -0
- package/ios/internals/ENRMViewFreeMeasurement.h +208 -0
- package/ios/internals/EnrichedTiptapTextComponentDescriptor.h +19 -0
- package/ios/internals/EnrichedTiptapTextShadowNode.h +43 -0
- package/ios/internals/EnrichedTiptapTextShadowNode.mm +69 -0
- package/ios/internals/EnrichedTiptapTextState.h +24 -0
- package/ios/internals/MeasurementCache.h +308 -0
- package/ios/internals/ShadowMeasurementUtils.h +145 -0
- package/ios/parser/ENRMTextLinkAttributes.h +7 -0
- package/ios/parser/ENRMTiptapParser.h +33 -0
- package/ios/parser/ENRMTiptapParser.mm +73 -0
- package/ios/parser/TiptapASTNode.h +57 -0
- package/ios/parser/TiptapASTNode.m +52 -0
- package/ios/parser/TiptapParserBridge.mm +179 -0
- package/ios/renderer/AttributedRenderer.h +23 -0
- package/ios/renderer/AttributedRenderer.m +229 -0
- package/ios/renderer/BaseRenderer.h +33 -0
- package/ios/renderer/BaseRenderer.m +46 -0
- package/ios/renderer/BaselineShiftTextAttributes.h +10 -0
- package/ios/renderer/BaselineShiftTextAttributes.m +26 -0
- package/ios/renderer/BlankLineRenderer.h +4 -0
- package/ios/renderer/BlankLineRenderer.m +51 -0
- package/ios/renderer/BlockquoteRenderer.h +6 -0
- package/ios/renderer/BlockquoteRenderer.m +258 -0
- package/ios/renderer/CodeBlockRenderer.h +9 -0
- package/ios/renderer/CodeBlockRenderer.m +99 -0
- package/ios/renderer/CodeRenderer.h +9 -0
- package/ios/renderer/CodeRenderer.m +69 -0
- package/ios/renderer/ENRMBlockquoteTextRenderer.h +25 -0
- package/ios/renderer/ENRMBlockquoteTextRenderer.m +48 -0
- package/ios/renderer/EmphasisRenderer.h +5 -0
- package/ios/renderer/EmphasisRenderer.m +100 -0
- package/ios/renderer/FactoidRenderer.h +9 -0
- package/ios/renderer/FactoidRenderer.m +130 -0
- package/ios/renderer/HeadingRenderer.h +6 -0
- package/ios/renderer/HeadingRenderer.m +103 -0
- package/ios/renderer/HighlightRenderer.h +7 -0
- package/ios/renderer/HighlightRenderer.m +33 -0
- package/ios/renderer/LinkRenderer.h +6 -0
- package/ios/renderer/LinkRenderer.m +158 -0
- package/ios/renderer/ListItemRenderer.h +24 -0
- package/ios/renderer/ListItemRenderer.m +283 -0
- package/ios/renderer/ListRenderer.h +13 -0
- package/ios/renderer/ListRenderer.m +126 -0
- package/ios/renderer/MentionRenderer.h +9 -0
- package/ios/renderer/MentionRenderer.m +96 -0
- package/ios/renderer/NodeRenderer.h +8 -0
- package/ios/renderer/ParagraphRenderer.h +6 -0
- package/ios/renderer/ParagraphRenderer.m +85 -0
- package/ios/renderer/RenderContext.h +145 -0
- package/ios/renderer/RenderContext.m +403 -0
- package/ios/renderer/RendererFactory.h +12 -0
- package/ios/renderer/RendererFactory.m +158 -0
- package/ios/renderer/StrikethroughRenderer.h +5 -0
- package/ios/renderer/StrikethroughRenderer.m +30 -0
- package/ios/renderer/StrongRenderer.h +5 -0
- package/ios/renderer/StrongRenderer.m +88 -0
- package/ios/renderer/TextRenderer.h +6 -0
- package/ios/renderer/TextRenderer.m +18 -0
- package/ios/renderer/ThematicBreakRenderer.h +4 -0
- package/ios/renderer/ThematicBreakRenderer.m +42 -0
- package/ios/renderer/UnderlineRenderer.h +4 -0
- package/ios/renderer/UnderlineRenderer.m +41 -0
- package/ios/styles/ENRMFontSlot.h +12 -0
- package/ios/styles/ENRMFontSlot.m +24 -0
- package/ios/styles/StyleConfig.h +488 -0
- package/ios/styles/StyleConfig.mm +2820 -0
- package/ios/utils/AccessibilityInfo.h +35 -0
- package/ios/utils/AccessibilityInfo.m +24 -0
- package/ios/utils/BlockquoteBorder.h +26 -0
- package/ios/utils/BlockquoteBorder.m +294 -0
- package/ios/utils/CodeBackground.h +19 -0
- package/ios/utils/CodeBackground.m +197 -0
- package/ios/utils/CodeBlockBackground.h +17 -0
- package/ios/utils/CodeBlockBackground.m +103 -0
- package/ios/utils/ContextMenuUtils.h +76 -0
- package/ios/utils/ContextMenuUtils.mm +75 -0
- package/ios/utils/ENRMAccessibilityLabels.h +40 -0
- package/ios/utils/ENRMAccessibilityLabels.m +5 -0
- package/ios/utils/ENRMAsyncRenderCoordinator.h +24 -0
- package/ios/utils/ENRMAsyncRenderCoordinator.m +37 -0
- package/ios/utils/ENRMAtomicSize.h +65 -0
- package/ios/utils/ENRMCodeBlockContent.h +37 -0
- package/ios/utils/ENRMCodeBlockContent.mm +89 -0
- package/ios/utils/ENRMFeatureFlags.h +25 -0
- package/ios/utils/ENRMImageDownloader.h +30 -0
- package/ios/utils/ENRMImageDownloader.m +168 -0
- package/ios/utils/ENRMLatexErrorCoordinator.h +27 -0
- package/ios/utils/ENRMLatexErrorCoordinator.mm +75 -0
- package/ios/utils/ENRMLatexErrorReporting.h +13 -0
- package/ios/utils/ENRMLinkContextMenus.h +93 -0
- package/ios/utils/ENRMLinkContextMenus.m +178 -0
- package/ios/utils/ENRMLinkRegexConfig.h +30 -0
- package/ios/utils/ENRMLinkRegexConfig.mm +104 -0
- package/ios/utils/ENRMLinkRegexProps.h +23 -0
- package/ios/utils/ENRMLocalImageLoader.h +35 -0
- package/ios/utils/ENRMLocalImageLoader.m +111 -0
- package/ios/utils/ENRMMenuAction.h +27 -0
- package/ios/utils/ENRMMenuAction.m +33 -0
- package/ios/utils/ENRMSpoilerOverlayManager.h +15 -0
- package/ios/utils/ENRMSpoilerOverlayManager.m +19 -0
- package/ios/utils/ENRMSpoilerTapUtils.h +6 -0
- package/ios/utils/ENRMSpoilerTapUtils.m +11 -0
- package/ios/utils/ENRMTailFadeInAnimator.h +16 -0
- package/ios/utils/ENRMTailFadeInAnimator.m +161 -0
- package/ios/utils/ENRMTextHitTest.h +23 -0
- package/ios/utils/ENRMTextHitTest.m +20 -0
- package/ios/utils/ENRMTextInteractionUtils.h +20 -0
- package/ios/utils/ENRMTextInteractionUtils.m +15 -0
- package/ios/utils/ENRMTextRenderer.h +38 -0
- package/ios/utils/ENRMTextRenderer.m +54 -0
- package/ios/utils/ENRMTextViewSetup.h +132 -0
- package/ios/utils/ENRMUIKit.h +429 -0
- package/ios/utils/EditMenuUtils.h +105 -0
- package/ios/utils/EditMenuUtils.m +143 -0
- package/ios/utils/FactoidBackground.h +20 -0
- package/ios/utils/FactoidBackground.m +161 -0
- package/ios/utils/FontScaleObserver.h +10 -0
- package/ios/utils/FontScaleObserver.m +55 -0
- package/ios/utils/FontUtils.h +31 -0
- package/ios/utils/FontUtils.m +63 -0
- package/ios/utils/HTMLGenerator.h +25 -0
- package/ios/utils/HTMLGenerator.m +1041 -0
- package/ios/utils/HeightUpdateUtils.h +25 -0
- package/ios/utils/ImageRequestHeaderUtils.h +35 -0
- package/ios/utils/LastElementUtils.h +97 -0
- package/ios/utils/LinkContextMenuUtils.h +55 -0
- package/ios/utils/LinkPillContentUtils.h +46 -0
- package/ios/utils/LinkTapUtils.h +56 -0
- package/ios/utils/LinkTapUtils.m +139 -0
- package/ios/utils/ListMarkerDrawer.h +15 -0
- package/ios/utils/ListMarkerDrawer.m +239 -0
- package/ios/utils/MentionBackground.h +26 -0
- package/ios/utils/MentionBackground.m +86 -0
- package/ios/utils/ParagraphStyleUtils.h +87 -0
- package/ios/utils/ParagraphStyleUtils.m +484 -0
- package/ios/utils/PasteboardUtils.h +48 -0
- package/ios/utils/PasteboardUtils.m +166 -0
- package/ios/utils/RTFExportUtils.h +24 -0
- package/ios/utils/RTFExportUtils.m +299 -0
- package/ios/utils/RuntimeKeys.h +44 -0
- package/ios/utils/RuntimeKeys.m +13 -0
- package/ios/utils/SelectionColorUtils.h +14 -0
- package/ios/utils/StylePropsUtils.h +1340 -0
- package/ios/utils/TaskListTapUtils.h +6 -0
- package/ios/utils/TaskListTapUtils.m +14 -0
- package/ios/utils/TextViewLayoutManager.h +14 -0
- package/ios/utils/TextViewLayoutManager.mm +198 -0
- package/ios/utils/TiptapAccessibilityElementBuilder.h +43 -0
- package/ios/utils/TiptapAccessibilityElementBuilder.m +432 -0
- package/ios/utils/TiptapExtractor.h +17 -0
- package/ios/utils/TiptapExtractor.m +367 -0
- package/ios/views/ENRMTiptapTextView.h +25 -0
- package/ios/views/ENRMTiptapTextView.m +247 -0
- package/package.json +70 -6
- package/react-native.config.js +10 -0
- package/src/EnrichedTiptapTextNativeComponent.ts +739 -0
- package/src/RichText.tsx +164 -0
- package/src/admonitionDefaults.ts +58 -0
- package/src/darkModeTextStyle.ts +99 -0
- package/src/headingDefaults.ts +21 -0
- package/src/index.tsx +4 -0
- package/src/linkVariantUtils.ts +120 -0
- package/src/normalizeTiptapStyle.ts +397 -0
- package/src/rn-globals.d.ts +1 -0
- package/src/styleUtils.ts +107 -0
- package/src/types/TiptapStyle.ts +532 -0
- package/src/types/TiptapStyleInternal.ts +299 -0
- package/src/types/linkPill.ts +9 -0
- package/src/utils/isDev.ts +4 -0
|
@@ -0,0 +1,179 @@
|
|
|
1
|
+
#import "ENRMTiptapParser.h"
|
|
2
|
+
#include "TiptapParser.hpp"
|
|
3
|
+
#import "TiptapASTNode.h"
|
|
4
|
+
#include "TiptapASTNode.hpp"
|
|
5
|
+
#import <React/RCTLog.h>
|
|
6
|
+
|
|
7
|
+
// Convert C++ AST node to Objective-C AST node
|
|
8
|
+
static TiptapASTNode *convertCppASTToObjC(std::shared_ptr<Tiptap::TiptapASTNode> cppNode)
|
|
9
|
+
{
|
|
10
|
+
if (!cppNode) {
|
|
11
|
+
return [[TiptapASTNode alloc] initWithType:TiptapNodeTypeDocument];
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
// Convert C++ NodeType enum to Objective-C TiptapNodeType
|
|
15
|
+
TiptapNodeType objcType;
|
|
16
|
+
switch (cppNode->type) {
|
|
17
|
+
case Tiptap::NodeType::Document:
|
|
18
|
+
objcType = TiptapNodeTypeDocument;
|
|
19
|
+
break;
|
|
20
|
+
case Tiptap::NodeType::Paragraph:
|
|
21
|
+
objcType = TiptapNodeTypeParagraph;
|
|
22
|
+
break;
|
|
23
|
+
case Tiptap::NodeType::Text:
|
|
24
|
+
objcType = TiptapNodeTypeText;
|
|
25
|
+
break;
|
|
26
|
+
case Tiptap::NodeType::Link:
|
|
27
|
+
objcType = TiptapNodeTypeLink;
|
|
28
|
+
break;
|
|
29
|
+
case Tiptap::NodeType::Heading:
|
|
30
|
+
objcType = TiptapNodeTypeHeading;
|
|
31
|
+
break;
|
|
32
|
+
case Tiptap::NodeType::LineBreak:
|
|
33
|
+
objcType = TiptapNodeTypeLineBreak;
|
|
34
|
+
break;
|
|
35
|
+
case Tiptap::NodeType::Strong:
|
|
36
|
+
objcType = TiptapNodeTypeStrong;
|
|
37
|
+
break;
|
|
38
|
+
case Tiptap::NodeType::Emphasis:
|
|
39
|
+
objcType = TiptapNodeTypeEmphasis;
|
|
40
|
+
break;
|
|
41
|
+
case Tiptap::NodeType::Strikethrough:
|
|
42
|
+
objcType = TiptapNodeTypeStrikethrough;
|
|
43
|
+
break;
|
|
44
|
+
case Tiptap::NodeType::Underline:
|
|
45
|
+
objcType = TiptapNodeTypeUnderline;
|
|
46
|
+
break;
|
|
47
|
+
case Tiptap::NodeType::Code:
|
|
48
|
+
objcType = TiptapNodeTypeCode;
|
|
49
|
+
break;
|
|
50
|
+
case Tiptap::NodeType::Image:
|
|
51
|
+
objcType = TiptapNodeTypeImage;
|
|
52
|
+
break;
|
|
53
|
+
case Tiptap::NodeType::Blockquote:
|
|
54
|
+
objcType = TiptapNodeTypeBlockquote;
|
|
55
|
+
break;
|
|
56
|
+
case Tiptap::NodeType::UnorderedList:
|
|
57
|
+
objcType = TiptapNodeTypeUnorderedList;
|
|
58
|
+
break;
|
|
59
|
+
case Tiptap::NodeType::OrderedList:
|
|
60
|
+
objcType = TiptapNodeTypeOrderedList;
|
|
61
|
+
break;
|
|
62
|
+
case Tiptap::NodeType::ListItem:
|
|
63
|
+
objcType = TiptapNodeTypeListItem;
|
|
64
|
+
break;
|
|
65
|
+
case Tiptap::NodeType::CodeBlock:
|
|
66
|
+
objcType = TiptapNodeTypeCodeBlock;
|
|
67
|
+
break;
|
|
68
|
+
case Tiptap::NodeType::ThematicBreak:
|
|
69
|
+
objcType = TiptapNodeTypeThematicBreak;
|
|
70
|
+
break;
|
|
71
|
+
case Tiptap::NodeType::Table:
|
|
72
|
+
objcType = TiptapNodeTypeTable;
|
|
73
|
+
break;
|
|
74
|
+
case Tiptap::NodeType::TableHead:
|
|
75
|
+
objcType = TiptapNodeTypeTableHead;
|
|
76
|
+
break;
|
|
77
|
+
case Tiptap::NodeType::TableBody:
|
|
78
|
+
objcType = TiptapNodeTypeTableBody;
|
|
79
|
+
break;
|
|
80
|
+
case Tiptap::NodeType::TableRow:
|
|
81
|
+
objcType = TiptapNodeTypeTableRow;
|
|
82
|
+
break;
|
|
83
|
+
case Tiptap::NodeType::TableHeaderCell:
|
|
84
|
+
objcType = TiptapNodeTypeTableHeaderCell;
|
|
85
|
+
break;
|
|
86
|
+
case Tiptap::NodeType::TableCell:
|
|
87
|
+
objcType = TiptapNodeTypeTableCell;
|
|
88
|
+
break;
|
|
89
|
+
case Tiptap::NodeType::LatexMathInline:
|
|
90
|
+
objcType = TiptapNodeTypeLatexMathInline;
|
|
91
|
+
break;
|
|
92
|
+
case Tiptap::NodeType::LatexMathDisplay:
|
|
93
|
+
objcType = TiptapNodeTypeLatexMathDisplay;
|
|
94
|
+
break;
|
|
95
|
+
case Tiptap::NodeType::Spoiler:
|
|
96
|
+
objcType = TiptapNodeTypeSpoiler;
|
|
97
|
+
break;
|
|
98
|
+
case Tiptap::NodeType::Superscript:
|
|
99
|
+
objcType = TiptapNodeTypeSuperscript;
|
|
100
|
+
break;
|
|
101
|
+
case Tiptap::NodeType::Subscript:
|
|
102
|
+
objcType = TiptapNodeTypeSubscript;
|
|
103
|
+
break;
|
|
104
|
+
case Tiptap::NodeType::Highlight:
|
|
105
|
+
objcType = TiptapNodeTypeHighlight;
|
|
106
|
+
break;
|
|
107
|
+
case Tiptap::NodeType::SoftBreak:
|
|
108
|
+
objcType = TiptapNodeTypeSoftBreak;
|
|
109
|
+
break;
|
|
110
|
+
case Tiptap::NodeType::BlankLine:
|
|
111
|
+
objcType = TiptapNodeTypeBlankLine;
|
|
112
|
+
break;
|
|
113
|
+
case Tiptap::NodeType::Admonition:
|
|
114
|
+
objcType = TiptapNodeTypeAdmonition;
|
|
115
|
+
break;
|
|
116
|
+
case Tiptap::NodeType::Video:
|
|
117
|
+
objcType = TiptapNodeTypeVideo;
|
|
118
|
+
break;
|
|
119
|
+
case Tiptap::NodeType::Factoid:
|
|
120
|
+
objcType = TiptapNodeTypeFactoid;
|
|
121
|
+
break;
|
|
122
|
+
case Tiptap::NodeType::Mention:
|
|
123
|
+
objcType = TiptapNodeTypeMention;
|
|
124
|
+
break;
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
TiptapASTNode *objcNode = [[TiptapASTNode alloc] initWithType:objcType];
|
|
128
|
+
|
|
129
|
+
// Convert content
|
|
130
|
+
if (!cppNode->content.empty()) {
|
|
131
|
+
objcNode.content = [NSString stringWithUTF8String:cppNode->content.c_str()];
|
|
132
|
+
}
|
|
133
|
+
|
|
134
|
+
// Convert attributes
|
|
135
|
+
for (const auto &[key, value] : cppNode->attributes) {
|
|
136
|
+
NSString *objcKey = [NSString stringWithUTF8String:key.c_str()];
|
|
137
|
+
NSString *objcValue = [NSString stringWithUTF8String:value.c_str()];
|
|
138
|
+
[objcNode setAttribute:objcKey value:objcValue];
|
|
139
|
+
}
|
|
140
|
+
|
|
141
|
+
// Convert children recursively
|
|
142
|
+
for (const auto &child : cppNode->children) {
|
|
143
|
+
TiptapASTNode *objcChild = convertCppASTToObjC(child);
|
|
144
|
+
[objcNode addChild:objcChild];
|
|
145
|
+
}
|
|
146
|
+
|
|
147
|
+
return objcNode;
|
|
148
|
+
}
|
|
149
|
+
|
|
150
|
+
TiptapASTNode *parseTiptapWithCppParser(NSString *document, ENRMMd4cFlags *flags, BOOL isGFM,
|
|
151
|
+
ENRMLinkRegexConfig *textRegex, ENRMLinkRegexConfig *codeRegex);
|
|
152
|
+
|
|
153
|
+
TiptapASTNode *parseTiptapWithCppParser(NSString *document, ENRMMd4cFlags *flags, BOOL isGFM)
|
|
154
|
+
{
|
|
155
|
+
return parseTiptapWithCppParser(document, flags, isGFM, nil, nil);
|
|
156
|
+
}
|
|
157
|
+
|
|
158
|
+
// Flags and link-regex arguments are ignored. The string is a Tiptap document.
|
|
159
|
+
TiptapASTNode *parseTiptapWithCppParser(NSString *document, ENRMMd4cFlags *flags, BOOL isGFM,
|
|
160
|
+
ENRMLinkRegexConfig *textRegex, ENRMLinkRegexConfig *codeRegex)
|
|
161
|
+
{
|
|
162
|
+
(void)flags;
|
|
163
|
+
(void)isGFM;
|
|
164
|
+
(void)textRegex;
|
|
165
|
+
(void)codeRegex;
|
|
166
|
+
|
|
167
|
+
if (document.length == 0) {
|
|
168
|
+
return [[TiptapASTNode alloc] initWithType:TiptapNodeTypeDocument];
|
|
169
|
+
}
|
|
170
|
+
|
|
171
|
+
const char *utf8String = [document UTF8String];
|
|
172
|
+
if (!utf8String) {
|
|
173
|
+
RCTLogError(@"TiptapParserBridge: Failed to convert document to UTF-8");
|
|
174
|
+
return [[TiptapASTNode alloc] initWithType:TiptapNodeTypeDocument];
|
|
175
|
+
}
|
|
176
|
+
|
|
177
|
+
auto cppAST = Tiptap::parseTiptapDocument(std::string(utf8String));
|
|
178
|
+
return convertCppASTToObjC(cppAST);
|
|
179
|
+
}
|
|
@@ -0,0 +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
|
|
@@ -0,0 +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
|
|
@@ -0,0 +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
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
#import "BaseRenderer.h"
|
|
2
|
+
#import "RenderContext.h"
|
|
3
|
+
#import "RendererFactory.h"
|
|
4
|
+
#import "StyleConfig.h"
|
|
5
|
+
|
|
6
|
+
@implementation BaseRenderer
|
|
7
|
+
|
|
8
|
+
- (instancetype)initWithRendererFactory:(id)rendererFactory config:(id)config
|
|
9
|
+
{
|
|
10
|
+
if (self = [super init]) {
|
|
11
|
+
_rendererFactory = rendererFactory;
|
|
12
|
+
_config = (StyleConfig *)config;
|
|
13
|
+
}
|
|
14
|
+
return self;
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
- (void)renderNode:(TiptapASTNode *)node into:(NSMutableAttributedString *)output context:(RenderContext *)context
|
|
18
|
+
{
|
|
19
|
+
id snapshot = [self takeContextSnapshot:context];
|
|
20
|
+
@try {
|
|
21
|
+
[self renderNodeContent:node into:output context:context];
|
|
22
|
+
} @finally {
|
|
23
|
+
[self restoreContextSnapshot:snapshot context:context];
|
|
24
|
+
}
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
- (void)renderNodeContent:(TiptapASTNode *)node
|
|
28
|
+
into:(NSMutableAttributedString *)output
|
|
29
|
+
context:(RenderContext *)context
|
|
30
|
+
{
|
|
31
|
+
[self doesNotRecognizeSelector:_cmd];
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
- (id)takeContextSnapshot:(RenderContext *)context
|
|
35
|
+
{
|
|
36
|
+
return nil;
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
- (void)restoreContextSnapshot:(id)snapshot context:(RenderContext *)context
|
|
40
|
+
{
|
|
41
|
+
if (snapshot) {
|
|
42
|
+
[context restoreScope:snapshot];
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
@end
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
#pragma once
|
|
2
|
+
#import "ENRMUIKit.h"
|
|
3
|
+
#import <Foundation/Foundation.h>
|
|
4
|
+
|
|
5
|
+
extern NSString *const ENRMScriptAttributeName;
|
|
6
|
+
extern NSString *const ENRMScriptValueSuperscript;
|
|
7
|
+
extern NSString *const ENRMScriptValueSubscript;
|
|
8
|
+
|
|
9
|
+
void ENRMApplyBaselineShift(NSMutableAttributedString *output, NSRange range, CGFloat fontScale,
|
|
10
|
+
CGFloat baselineOffsetScale);
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
#import "BaselineShiftTextAttributes.h"
|
|
2
|
+
|
|
3
|
+
NSString *const ENRMScriptAttributeName = @"ENRMScript";
|
|
4
|
+
NSString *const ENRMScriptValueSuperscript = @"superscript";
|
|
5
|
+
NSString *const ENRMScriptValueSubscript = @"subscript";
|
|
6
|
+
|
|
7
|
+
void ENRMApplyBaselineShift(NSMutableAttributedString *output, NSRange range, CGFloat fontScale,
|
|
8
|
+
CGFloat baselineOffsetScale)
|
|
9
|
+
{
|
|
10
|
+
[output enumerateAttribute:NSFontAttributeName
|
|
11
|
+
inRange:range
|
|
12
|
+
options:NSAttributedStringEnumerationLongestEffectiveRangeNotRequired
|
|
13
|
+
usingBlock:^(UIFont *font, NSRange fontRange, BOOL *stop) {
|
|
14
|
+
(void)stop;
|
|
15
|
+
if (![font isKindOfClass:UIFont.class]) {
|
|
16
|
+
return;
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
UIFont *scaledFont = [UIFont fontWithDescriptor:font.fontDescriptor
|
|
20
|
+
size:font.pointSize * fontScale];
|
|
21
|
+
[output addAttribute:NSFontAttributeName value:scaledFont range:fontRange];
|
|
22
|
+
[output addAttribute:NSBaselineOffsetAttributeName
|
|
23
|
+
value:@(font.pointSize * baselineOffsetScale)
|
|
24
|
+
range:fontRange];
|
|
25
|
+
}];
|
|
26
|
+
}
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
#import "BlankLineRenderer.h"
|
|
2
|
+
#import "TiptapASTNode.h"
|
|
3
|
+
#import "ParagraphStyleUtils.h"
|
|
4
|
+
#import "StyleConfig.h"
|
|
5
|
+
|
|
6
|
+
#pragma mark - Renderer Implementation
|
|
7
|
+
|
|
8
|
+
// Renders a run of consecutive blank lines emitted by the parser when the
|
|
9
|
+
// preserveBlankLines flag is enabled. Each blank line in the source is drawn as
|
|
10
|
+
// one empty line, so the rendered text keeps the exact line count that was typed
|
|
11
|
+
// (e.g. in EnrichedTiptapTextInput). The empty lines use the paragraph font
|
|
12
|
+
// and line height so their vertical rhythm matches the surrounding paragraphs;
|
|
13
|
+
// any extra block spacing is left to the caller to configure via tiptapStyle.
|
|
14
|
+
@implementation BlankLineRenderer
|
|
15
|
+
|
|
16
|
+
- (void)renderNodeContent:(TiptapASTNode *)node
|
|
17
|
+
into:(NSMutableAttributedString *)output
|
|
18
|
+
context:(RenderContext *)context
|
|
19
|
+
{
|
|
20
|
+
NSInteger count = [node.attributes[@"count"] integerValue];
|
|
21
|
+
if (count <= 0) {
|
|
22
|
+
return;
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
[self ensureStartingNewline:output];
|
|
26
|
+
|
|
27
|
+
NSDictionary *attributes = @{NSFontAttributeName : _config.paragraphFont};
|
|
28
|
+
|
|
29
|
+
NSMutableString *blanks = [NSMutableString stringWithCapacity:(NSUInteger)count];
|
|
30
|
+
for (NSInteger i = 0; i < count; i++) {
|
|
31
|
+
[blanks appendString:@"\n"];
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
NSUInteger start = output.length;
|
|
35
|
+
[output appendAttributedString:[[NSAttributedString alloc] initWithString:blanks attributes:attributes]];
|
|
36
|
+
|
|
37
|
+
NSRange range = NSMakeRange(start, output.length - start);
|
|
38
|
+
applyLineHeight(output, range, _config.paragraphLineHeight);
|
|
39
|
+
applyTextAlignment(output, range, _config.paragraphTextAlign);
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
#pragma mark - Private Utilities
|
|
43
|
+
|
|
44
|
+
- (void)ensureStartingNewline:(NSMutableAttributedString *)output
|
|
45
|
+
{
|
|
46
|
+
if (output.length > 0 && ![output.string hasSuffix:@"\n"]) {
|
|
47
|
+
[output appendAttributedString:[[NSAttributedString alloc] initWithString:@"\n"]];
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
@end
|