react-native-enriched-markdown-scaffold 0.7.4-scaffold.9 → 1.0.2-scaffold.10
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +54 -8
- package/ReactNativeEnrichedMarkdown.podspec +82 -73
- package/android/build.gradle +188 -1
- package/android/consumer-rules.pro +1 -1
- package/android/generated/java/com/facebook/react/viewmanagers/EnrichedMarkdownManagerDelegate.java +27 -0
- package/android/generated/java/com/facebook/react/viewmanagers/EnrichedMarkdownManagerInterface.java +7 -0
- package/android/generated/java/com/facebook/react/viewmanagers/EnrichedMarkdownTextInputManagerDelegate.java +24 -0
- package/android/generated/java/com/facebook/react/viewmanagers/EnrichedMarkdownTextInputManagerInterface.java +8 -0
- package/android/generated/java/com/facebook/react/viewmanagers/EnrichedMarkdownTextManagerDelegate.java +27 -0
- package/android/generated/java/com/facebook/react/viewmanagers/EnrichedMarkdownTextManagerInterface.java +7 -0
- package/android/generated/jni/react/renderer/components/EnrichedMarkdownTextSpec/EventEmitters.cpp +223 -0
- package/android/generated/jni/react/renderer/components/EnrichedMarkdownTextSpec/EventEmitters.h +183 -0
- package/android/generated/jni/react/renderer/components/EnrichedMarkdownTextSpec/Props.cpp +65 -0
- package/android/generated/jni/react/renderer/components/EnrichedMarkdownTextSpec/Props.h +1086 -61
- package/android/src/main/baseline-prof.txt +1 -1
- package/android/src/main/cpp/jni-adapter.cpp +74 -0
- package/android/src/main/java/com/swmansion/enriched/markdown/EnrichedMarkdown.kt +351 -13
- package/android/src/main/java/com/swmansion/enriched/markdown/EnrichedMarkdownInternalText.kt +62 -0
- package/android/src/main/java/com/swmansion/enriched/markdown/EnrichedMarkdownManager.kt +85 -0
- package/android/src/main/java/com/swmansion/enriched/markdown/EnrichedMarkdownText.kt +160 -1
- package/android/src/main/java/com/swmansion/enriched/markdown/EnrichedMarkdownTextLayoutManager.kt +10 -1
- package/android/src/main/java/com/swmansion/enriched/markdown/EnrichedMarkdownTextManager.kt +76 -0
- package/android/src/main/java/com/swmansion/enriched/markdown/MeasurementStore.kt +126 -10
- package/android/src/main/java/com/swmansion/enriched/markdown/events/CopyPressEvent.kt +24 -0
- package/android/src/main/java/com/swmansion/enriched/markdown/events/CopyRequestEvent.kt +28 -0
- package/android/src/main/java/com/swmansion/enriched/markdown/events/LinkLayoutEvent.kt +36 -0
- package/android/src/main/java/com/swmansion/enriched/markdown/events/SelectionChangeEvent.kt +43 -0
- package/android/src/main/java/com/swmansion/enriched/markdown/input/EnrichedMarkdownTextInputManager.kt +54 -4
- package/android/src/main/java/com/swmansion/enriched/markdown/input/EnrichedMarkdownTextInputView.kt +923 -462
- package/android/src/main/java/com/swmansion/enriched/markdown/input/MarkdownClipboard.kt +42 -0
- package/android/src/main/java/com/swmansion/enriched/markdown/input/editing/BlockEditCoordinator.kt +196 -0
- package/android/src/main/java/com/swmansion/enriched/markdown/input/editing/ClipboardCoordinator.kt +73 -0
- package/android/src/main/java/com/swmansion/enriched/markdown/input/editing/EditContext.kt +19 -0
- package/android/src/main/java/com/swmansion/enriched/markdown/input/editing/EditPipeline.kt +248 -0
- package/android/src/main/java/com/swmansion/enriched/markdown/input/editing/EditSession.kt +52 -0
- package/android/src/main/java/com/swmansion/enriched/markdown/input/editing/InputConnectionWrapper.kt +108 -7
- package/android/src/main/java/com/swmansion/enriched/markdown/input/editing/LinkCoordinator.kt +69 -0
- package/android/src/main/java/com/swmansion/enriched/markdown/input/editing/MarkdownTextWatcher.kt +3 -3
- package/android/src/main/java/com/swmansion/enriched/markdown/input/editing/MentionCoordinator.kt +118 -0
- package/android/src/main/java/com/swmansion/enriched/markdown/input/events/OnChangeStateEvent.kt +26 -0
- package/android/src/main/java/com/swmansion/enriched/markdown/input/events/OnContextMenuItemPressEvent.kt +26 -0
- package/android/src/main/java/com/swmansion/enriched/markdown/input/events/OnInputKeyPressEvent.kt +24 -0
- package/android/src/main/java/com/swmansion/enriched/markdown/input/events/OnPasteEvent.kt +24 -0
- package/android/src/main/java/com/swmansion/enriched/markdown/input/formatting/BlockStore.kt +254 -0
- package/android/src/main/java/com/swmansion/enriched/markdown/input/formatting/FormattingStore.kt +80 -87
- package/android/src/main/java/com/swmansion/enriched/markdown/input/formatting/InputFormatter.kt +109 -1
- package/android/src/main/java/com/swmansion/enriched/markdown/input/formatting/InputParser.kt +116 -22
- package/android/src/main/java/com/swmansion/enriched/markdown/input/formatting/MarkdownSerializer.kt +167 -38
- package/android/src/main/java/com/swmansion/enriched/markdown/input/formatting/RangeEditAdjustment.kt +149 -0
- package/android/src/main/java/com/swmansion/enriched/markdown/input/layout/InputEventEmitter.kt +66 -5
- package/android/src/main/java/com/swmansion/enriched/markdown/input/layout/InputMeasurementStore.kt +4 -2
- package/android/src/main/java/com/swmansion/enriched/markdown/input/model/BlockRange.kt +27 -0
- package/android/src/main/java/com/swmansion/enriched/markdown/input/model/BlockType.kt +48 -0
- package/android/src/main/java/com/swmansion/enriched/markdown/input/model/FormattingRange.kt +9 -4
- package/android/src/main/java/com/swmansion/enriched/markdown/input/model/InputFormatterStyle.kt +39 -2
- package/android/src/main/java/com/swmansion/enriched/markdown/input/model/MathAtom.kt +20 -0
- package/android/src/main/java/com/swmansion/enriched/markdown/input/model/MathChipStyle.kt +1 -1
- package/android/src/main/java/com/swmansion/enriched/markdown/input/model/MutableRangeBounds.kt +11 -0
- package/android/src/main/java/com/swmansion/enriched/markdown/input/spans/InputBulletSpan.kt +82 -0
- package/android/src/main/java/com/swmansion/enriched/markdown/input/spans/InputHeadingSpan.kt +58 -0
- package/android/src/main/java/com/swmansion/enriched/markdown/input/spans/InputListItemSpacingSpan.kt +37 -0
- package/android/src/main/java/com/swmansion/enriched/markdown/input/spans/InputOrderedListMarkerSpan.kt +63 -0
- package/android/src/main/java/com/swmansion/enriched/markdown/input/styles/BlockHandler.kt +54 -0
- package/android/src/main/java/com/swmansion/enriched/markdown/input/styles/HeadingBlockHandler.kt +27 -0
- package/android/src/main/java/com/swmansion/enriched/markdown/input/styles/OrderedListBlockHandler.kt +38 -0
- package/android/src/main/java/com/swmansion/enriched/markdown/input/styles/UnorderedListBlockHandler.kt +37 -0
- package/android/src/main/java/com/swmansion/enriched/markdown/input/toolbar/InputContextMenu.kt +8 -26
- package/android/src/main/java/com/swmansion/enriched/markdown/parser/MarkdownASTNode.kt +1 -0
- package/android/src/main/java/com/swmansion/enriched/markdown/parser/Parser.kt +1 -0
- package/android/src/main/java/com/swmansion/enriched/markdown/renderer/BlockStyleContext.kt +9 -2
- package/android/src/main/java/com/swmansion/enriched/markdown/renderer/BlockquoteRenderer.kt +100 -12
- package/android/src/main/java/com/swmansion/enriched/markdown/renderer/CodeBlockRenderer.kt +16 -1
- package/android/src/main/java/com/swmansion/enriched/markdown/renderer/HeadingRenderer.kt +4 -0
- package/android/src/main/java/com/swmansion/enriched/markdown/renderer/LinkRenderer.kt +37 -7
- package/android/src/main/java/com/swmansion/enriched/markdown/renderer/ListContextManager.kt +2 -1
- package/android/src/main/java/com/swmansion/enriched/markdown/renderer/ListItemRenderer.kt +74 -18
- package/android/src/main/java/com/swmansion/enriched/markdown/renderer/ListRenderer.kt +43 -4
- package/android/src/main/java/com/swmansion/enriched/markdown/renderer/NodeRenderer.kt +9 -1
- package/android/src/main/java/com/swmansion/enriched/markdown/renderer/SoftBreakRenderer.kt +16 -0
- package/android/src/main/java/com/swmansion/enriched/markdown/renderer/SpanStyleCache.kt +35 -28
- package/android/src/main/java/com/swmansion/enriched/markdown/spans/BaseListSpan.kt +24 -0
- package/android/src/main/java/com/swmansion/enriched/markdown/spans/BlockquoteSpan.kt +174 -24
- package/android/src/main/java/com/swmansion/enriched/markdown/spans/CodeBackgroundSpan.kt +20 -82
- package/android/src/main/java/com/swmansion/enriched/markdown/spans/CodeBlockSpan.kt +13 -16
- package/android/src/main/java/com/swmansion/enriched/markdown/spans/CodeSpan.kt +1 -1
- package/android/src/main/java/com/swmansion/enriched/markdown/spans/EmphasisSpan.kt +1 -1
- package/android/src/main/java/com/swmansion/enriched/markdown/spans/ImageSpan.kt +182 -46
- package/android/src/main/java/com/swmansion/enriched/markdown/spans/InlineChipPainter.kt +140 -0
- package/android/src/main/java/com/swmansion/enriched/markdown/spans/LinkChipSpans.kt +177 -0
- package/android/src/main/java/com/swmansion/enriched/markdown/spans/LinkSpan.kt +1 -6
- package/android/src/main/java/com/swmansion/enriched/markdown/spans/ListItemSpacingSpan.kt +33 -0
- package/android/src/main/java/com/swmansion/enriched/markdown/spans/ListMarkerAnchorSpan.kt +38 -0
- package/android/src/main/java/com/swmansion/enriched/markdown/spans/OrderedListSpan.kt +2 -0
- package/android/src/main/java/com/swmansion/enriched/markdown/spans/StrongSpan.kt +1 -1
- package/android/src/main/java/com/swmansion/enriched/markdown/spans/TaskListSpan.kt +3 -2
- package/android/src/main/java/com/swmansion/enriched/markdown/spans/UnorderedListSpan.kt +3 -2
- package/android/src/main/java/com/swmansion/enriched/markdown/styles/BlockquoteStyle.kt +6 -0
- package/android/src/main/java/com/swmansion/enriched/markdown/styles/CodeBlockStyle.kt +26 -0
- package/android/src/main/java/com/swmansion/enriched/markdown/styles/ImageStyle.kt +7 -1
- package/android/src/main/java/com/swmansion/enriched/markdown/styles/InlineMathStyle.kt +16 -1
- package/android/src/main/java/com/swmansion/enriched/markdown/styles/LinkStyle.kt +36 -1
- package/android/src/main/java/com/swmansion/enriched/markdown/styles/LinkVariantEntry.kt +7 -3
- package/android/src/main/java/com/swmansion/enriched/markdown/styles/ListStyle.kt +4 -1
- package/android/src/main/java/com/swmansion/enriched/markdown/styles/MathStyle.kt +3 -0
- package/android/src/main/java/com/swmansion/enriched/markdown/styles/StyleConfig.kt +13 -4
- package/android/src/main/java/com/swmansion/enriched/markdown/styles/TableStyle.kt +6 -0
- package/android/src/main/java/com/swmansion/enriched/markdown/utils/common/CodeBlockHighlighter.kt +90 -0
- package/android/src/main/java/com/swmansion/enriched/markdown/utils/common/CodeBlockNode.kt +57 -0
- package/android/src/main/java/com/swmansion/enriched/markdown/utils/common/FeatureFlags.kt +1 -0
- package/android/src/main/java/com/swmansion/enriched/markdown/utils/common/MarkdownSegment.kt +9 -0
- package/android/src/main/java/com/swmansion/enriched/markdown/utils/common/MarkdownViewManagerUtils.kt +84 -7
- package/android/src/main/java/com/swmansion/enriched/markdown/utils/common/ReadableMapExtensions.kt +3 -0
- package/android/src/main/java/com/swmansion/enriched/markdown/utils/common/RenderedSegment.kt +10 -0
- package/android/src/main/java/com/swmansion/enriched/markdown/utils/common/SegmentSignature.kt +1 -0
- package/android/src/main/java/com/swmansion/enriched/markdown/utils/common/StreamingMarkdownFilter.kt +83 -5
- package/android/src/main/java/com/swmansion/enriched/markdown/utils/common/serialization/MarkdownASTSerializer.kt +4 -0
- package/android/src/main/java/com/swmansion/enriched/markdown/utils/input/MarkdownStyleParser.kt +74 -44
- package/android/src/main/java/com/swmansion/enriched/markdown/utils/input/PasteTextUtils.kt +52 -0
- package/android/src/main/java/com/swmansion/enriched/markdown/utils/text/ImageCache.kt +26 -3
- package/android/src/main/java/com/swmansion/enriched/markdown/utils/text/ImageDownloader.kt +22 -9
- package/android/src/main/java/com/swmansion/enriched/markdown/utils/text/LocalImageLoader.kt +161 -0
- package/android/src/main/java/com/swmansion/enriched/markdown/utils/text/conversion/HTMLGenerator.kt +2 -1
- package/android/src/main/java/com/swmansion/enriched/markdown/utils/text/conversion/MarkdownExtractor.kt +6 -0
- package/android/src/main/java/com/swmansion/enriched/markdown/utils/text/extensions/TextPaintExtensions.kt +23 -0
- package/android/src/main/java/com/swmansion/enriched/markdown/utils/text/interaction/CheckboxTouchHelper.kt +7 -0
- package/android/src/main/java/com/swmansion/enriched/markdown/utils/text/interaction/TaskListTapUtils.kt +41 -21
- package/android/src/main/java/com/swmansion/enriched/markdown/utils/text/span/BlockSpacing.kt +15 -8
- package/android/src/main/java/com/swmansion/enriched/markdown/utils/text/view/HeadlessActionMode.kt +88 -0
- package/android/src/main/java/com/swmansion/enriched/markdown/utils/text/view/LinkLayoutCollector.kt +100 -0
- package/android/src/main/java/com/swmansion/enriched/markdown/utils/text/view/LinkLongPressMovementMethod.kt +58 -27
- package/android/src/main/java/com/swmansion/enriched/markdown/utils/text/view/SelectionActionMode.kt +72 -16
- package/android/src/main/java/com/swmansion/enriched/markdown/utils/text/view/SelectionChangeReporter.kt +232 -0
- package/android/src/main/java/com/swmansion/enriched/markdown/views/BlockMenuOptions.kt +64 -0
- package/android/src/main/java/com/swmansion/enriched/markdown/views/CodeBlockContainerView.kt +414 -0
- package/android/src/main/java/com/swmansion/enriched/markdown/views/ContextMenuPopup.kt +9 -6
- package/android/src/main/java/com/swmansion/enriched/markdown/views/CopyGlyph.kt +101 -0
- package/android/src/main/java/com/swmansion/enriched/markdown/views/TableContainerView.kt +61 -11
- package/android/src/main/jni/CMakeLists.txt +53 -0
- package/android/src/main/jni/react/renderer/components/EnrichedMarkdownTextSpec/MarkdownContainerShadowNode.cpp +10 -0
- package/android/src/main/jni/react/renderer/components/EnrichedMarkdownTextSpec/MarkdownContainerShadowNode.h +11 -2
- package/android/src/main/jni/react/renderer/components/EnrichedMarkdownTextSpec/MarkdownTextShadowNode.cpp +10 -0
- package/android/src/main/jni/react/renderer/components/EnrichedMarkdownTextSpec/MarkdownTextShadowNode.h +12 -2
- package/android/src/main/jni/react/renderer/components/EnrichedMarkdownTextSpec/MarkdownTextState.cpp +9 -0
- package/android/src/main/jni/react/renderer/components/EnrichedMarkdownTextSpec/MarkdownTextState.h +24 -0
- package/android/src/main/jni/react/renderer/components/EnrichedMarkdownTextSpec/conversions.h +16 -0
- package/android/src/math/java/com/swmansion/enriched/markdown/input/math/MathChipControllerImpl.kt +21 -4
- package/android/src/math/java/com/swmansion/enriched/markdown/renderer/MathInlineRenderer.kt +8 -2
- package/android/src/math/java/com/swmansion/enriched/markdown/spans/MathChipSpan.kt +1 -1
- package/android/src/math/java/com/swmansion/enriched/markdown/spans/MathInlineSpan.kt +13 -6
- package/android/src/math/java/com/swmansion/enriched/markdown/spans/MathMeasureHelper.kt +2 -1
- package/android/src/math/java/com/swmansion/enriched/markdown/views/MathContainerView.kt +26 -8
- package/cpp/highlight/CodeBlockHighlighter.cpp +284 -0
- package/cpp/highlight/CodeBlockHighlighter.hpp +66 -0
- package/cpp/highlight/CodeBlockLanguages.cpp +138 -0
- package/cpp/highlight/CodeBlockLanguages.hpp +25 -0
- package/cpp/highlight/HighlightGrammars.hpp +28 -0
- package/cpp/highlight/code_highlight_podspec.rb +211 -0
- package/cpp/highlight/gen-registry.mjs +155 -0
- package/cpp/highlight/grammar-versions.json +159 -0
- package/cpp/highlight/vendor/generated/generated_queries.h +1665 -0
- package/cpp/highlight/vendor/generated/generated_registry.cpp +59 -0
- package/cpp/parser/MD4CParser.cpp +173 -61
- package/cpp/parser/MD4CParser.hpp +1 -0
- package/cpp/parser/MarkdownASTNode.hpp +2 -1
- package/cpp/wasm/ASTSerializer.cpp +2 -0
- package/cpp/wasm/build.sh +1 -0
- package/cpp/wasm/md4c_wasm.cpp +3 -1
- package/docs/ACCESSIBILITY.md +14 -2
- package/docs/API_REFERENCE.md +405 -12
- package/docs/BREAKING_CHANGES.md +129 -0
- package/docs/CODE_HIGHLIGHT.md +133 -0
- package/docs/COPY_OPTIONS.md +61 -3
- package/docs/ELEMENTS_STRUCTURE.md +52 -4
- package/docs/IMAGE_CACHING.md +30 -0
- package/docs/INPUT.md +110 -11
- package/docs/LATEX_MATH.md +87 -45
- package/docs/MACOS.md +1 -1
- package/docs/MARKDOWN_STREAMING.md +27 -1
- package/docs/MENTIONS.md +8 -1
- package/docs/NATIVE_ASSETS.md +127 -0
- package/docs/RTL.md +1 -1
- package/docs/STYLES.md +73 -6
- package/docs/TESTING.md +112 -0
- package/docs/TEXT.md +18 -6
- package/docs/WEB.md +4 -1
- package/ios/EnrichedMarkdown.h +7 -0
- package/ios/EnrichedMarkdown.mm +583 -76
- package/ios/EnrichedMarkdownText.h +7 -0
- package/ios/EnrichedMarkdownText.mm +299 -73
- package/ios/attachments/ENRMImageAttachment.h +9 -0
- package/ios/attachments/ENRMImageAttachment.m +143 -40
- package/ios/attachments/ENRMMathInlineAttachment+macOS.m +2 -1
- package/ios/attachments/ENRMMathInlineAttachment.h +5 -0
- package/ios/attachments/ENRMMathInlineAttachment.m +50 -82
- package/ios/attachments/ENRMMathInlineAttachmentShared.h +2 -0
- package/ios/generated/ReactCodegen/EnrichedMarkdownTextSpec/EventEmitters.cpp +223 -0
- package/ios/generated/ReactCodegen/EnrichedMarkdownTextSpec/EventEmitters.h +183 -0
- package/ios/generated/ReactCodegen/EnrichedMarkdownTextSpec/Props.cpp +65 -0
- package/ios/generated/ReactCodegen/EnrichedMarkdownTextSpec/Props.h +1086 -61
- package/ios/generated/ReactCodegen/EnrichedMarkdownTextSpec/RCTComponentViewHelpers.h +181 -2
- package/ios/input/ENRMAutoLinkDetector.h +2 -1
- package/ios/input/ENRMAutoLinkDetector.mm +79 -41
- package/ios/input/ENRMBlockEditCoordinator.h +71 -0
- package/ios/input/ENRMBlockEditCoordinator.mm +195 -0
- package/ios/input/ENRMBlockRange.h +28 -0
- package/ios/input/ENRMBlockRange.mm +30 -0
- package/ios/input/ENRMBlockStore.h +56 -0
- package/ios/input/ENRMBlockStore.mm +275 -0
- package/ios/input/ENRMClipboardCoordinator.h +45 -0
- package/ios/input/ENRMClipboardCoordinator.mm +120 -0
- package/ios/input/ENRMDetectorPipeline.h +2 -1
- package/ios/input/ENRMEditPipeline.h +76 -0
- package/ios/input/ENRMEditPipeline.mm +228 -0
- package/ios/input/ENRMEditSession.h +36 -0
- package/ios/input/ENRMEditSession.mm +63 -0
- package/ios/input/ENRMFormattingStore.h +17 -0
- package/ios/input/ENRMFormattingStore.mm +95 -105
- package/ios/input/ENRMInputBlockType.h +91 -0
- package/ios/input/ENRMInputBlockType.mm +5 -0
- package/ios/input/ENRMInputDecorationDrawer.h +18 -0
- package/ios/input/ENRMInputEventEmitter.h +56 -0
- package/ios/input/ENRMInputEventEmitter.mm +308 -0
- package/ios/input/ENRMInputFormatter.h +29 -69
- package/ios/input/ENRMInputFormatter.mm +216 -124
- package/ios/input/ENRMInputFormatterStyle.h +99 -0
- package/ios/input/ENRMInputFormatterStyle.mm +188 -0
- package/ios/input/ENRMInputLayoutManager.h +9 -0
- package/ios/input/ENRMInputLayoutManager.mm +30 -0
- package/ios/input/ENRMInputListMarkerDrawer.h +32 -0
- package/ios/input/ENRMInputListMarkerDrawer.mm +426 -0
- package/ios/input/ENRMInputParser.h +5 -6
- package/ios/input/ENRMInputParser.mm +461 -178
- package/ios/input/ENRMInputRemend.mm +2 -2
- package/ios/input/ENRMInputStyleStateBuilder.h +40 -0
- package/ios/input/ENRMInputStyleStateBuilder.mm +60 -0
- package/ios/input/ENRMInputTextView.mm +103 -8
- package/ios/input/ENRMInputTypingAttributesController.h +42 -0
- package/ios/input/ENRMInputTypingAttributesController.mm +203 -0
- package/ios/input/ENRMLinkCoordinator.h +41 -0
- package/ios/input/ENRMLinkCoordinator.mm +89 -0
- package/ios/input/ENRMMarkdownSerializer.h +29 -5
- package/ios/input/ENRMMarkdownSerializer.mm +170 -48
- package/ios/input/ENRMMathAtom.h +26 -0
- package/ios/input/ENRMMathAtom.mm +12 -0
- package/ios/input/ENRMMentionCoordinator.h +45 -0
- package/ios/input/ENRMMentionCoordinator.mm +167 -0
- package/ios/input/ENRMRangeEditAdjustment.h +38 -0
- package/ios/input/ENRMRangeEditAdjustment.mm +91 -0
- package/ios/input/ENRMRangeStoreUtils.h +39 -0
- package/ios/input/EnrichedMarkdownTextInput+ContextMenu.mm +6 -6
- package/ios/input/EnrichedMarkdownTextInput+Internal.h +11 -3
- package/ios/input/EnrichedMarkdownTextInput.h +7 -1
- package/ios/input/EnrichedMarkdownTextInput.mm +1089 -1023
- package/ios/input/InputStylePropsUtils.h +109 -68
- package/ios/input/internals/EnrichedMarkdownTextInputShadowNode.mm +2 -1
- package/ios/input/styles/ENRMBlockHandler.h +46 -0
- package/ios/input/styles/ENRMHeadingBlockHandler.h +15 -0
- package/ios/input/styles/ENRMHeadingBlockHandler.mm +38 -0
- package/ios/input/styles/ENRMOrderedListBlockHandler.h +14 -0
- package/ios/input/styles/ENRMOrderedListBlockHandler.mm +48 -0
- package/ios/input/styles/ENRMUnorderedListBlockHandler.h +15 -0
- package/ios/input/styles/ENRMUnorderedListBlockHandler.mm +51 -0
- package/ios/internals/ENRMViewFreeMeasurement.h +331 -0
- package/ios/internals/EnrichedMarkdownShadowNode.h +1 -3
- package/ios/internals/EnrichedMarkdownShadowNode.mm +16 -20
- package/ios/internals/EnrichedMarkdownTextShadowNode.h +1 -3
- package/ios/internals/EnrichedMarkdownTextShadowNode.mm +15 -20
- package/ios/internals/MeasurementCache.h +41 -9
- package/ios/internals/ShadowMeasurementUtils.h +63 -58
- package/ios/math/ENRMMathChipController.h +74 -0
- package/ios/math/ENRMMathChipController.mm +476 -0
- package/ios/math/ENRMRaTeXBridge.swift +27 -6
- package/ios/parser/ENRMMarkdownParser.h +1 -8
- package/ios/parser/ENRMMarkdownParser.mm +2 -11
- package/ios/parser/MarkdownASTNode.h +2 -1
- package/ios/parser/MarkdownParserBridge.mm +4 -0
- package/ios/renderer/AttributedRenderer.m +20 -2
- package/ios/renderer/BaseRenderer.h +17 -2
- package/ios/renderer/BaseRenderer.m +30 -0
- package/ios/renderer/BlockquoteRenderer.h +1 -1
- package/ios/renderer/BlockquoteRenderer.m +144 -35
- package/ios/renderer/CodeBlockRenderer.h +1 -1
- package/ios/renderer/CodeBlockRenderer.m +27 -23
- package/ios/renderer/CodeRenderer.h +1 -1
- package/ios/renderer/CodeRenderer.m +3 -1
- package/ios/renderer/ENRMImageRenderer.h +1 -1
- package/ios/renderer/ENRMImageRenderer.m +5 -1
- package/ios/renderer/ENRMMathInlineRenderer.h +1 -1
- package/ios/renderer/ENRMMathInlineRenderer.m +6 -1
- package/ios/renderer/ENRMSpoilerRenderer.h +1 -1
- package/ios/renderer/ENRMSpoilerRenderer.m +3 -1
- package/ios/renderer/EmphasisRenderer.h +1 -1
- package/ios/renderer/EmphasisRenderer.m +3 -1
- package/ios/renderer/HeadingRenderer.h +1 -1
- package/ios/renderer/HeadingRenderer.m +13 -6
- package/ios/renderer/HighlightRenderer.h +1 -1
- package/ios/renderer/HighlightRenderer.m +3 -1
- package/ios/renderer/LinkRenderer.h +1 -1
- package/ios/renderer/LinkRenderer.m +50 -16
- package/ios/renderer/ListItemRenderer.h +13 -1
- package/ios/renderer/ListItemRenderer.m +102 -44
- package/ios/renderer/ListRenderer.h +2 -2
- package/ios/renderer/ListRenderer.m +63 -25
- package/ios/renderer/ParagraphRenderer.h +1 -1
- package/ios/renderer/ParagraphRenderer.m +16 -8
- package/ios/renderer/RenderContext.h +10 -0
- package/ios/renderer/RenderContext.m +44 -0
- package/ios/renderer/RendererFactory.m +14 -0
- package/ios/renderer/StrikethroughRenderer.h +1 -1
- package/ios/renderer/StrikethroughRenderer.m +3 -1
- package/ios/renderer/StrongRenderer.h +1 -1
- package/ios/renderer/StrongRenderer.m +3 -1
- package/ios/renderer/SubscriptRenderer.h +1 -1
- package/ios/renderer/SubscriptRenderer.m +3 -1
- package/ios/renderer/SuperscriptRenderer.h +1 -1
- package/ios/renderer/SuperscriptRenderer.m +3 -1
- package/ios/renderer/TextRenderer.h +2 -2
- package/ios/renderer/TextRenderer.m +3 -1
- package/ios/renderer/ThematicBreakRenderer.h +1 -1
- package/ios/renderer/ThematicBreakRenderer.m +3 -1
- package/ios/renderer/UnderlineRenderer.h +1 -1
- package/ios/renderer/UnderlineRenderer.m +3 -1
- package/ios/styles/StyleConfig.h +42 -0
- package/ios/styles/StyleConfig.mm +216 -0
- package/ios/utils/BlockquoteBorder.h +6 -0
- package/ios/utils/BlockquoteBorder.m +249 -52
- package/ios/utils/CodeBackground.m +3 -65
- package/ios/utils/CodeBlockBackground.m +16 -2
- package/ios/utils/ENRMAtomicSize.h +65 -0
- package/ios/utils/ENRMBlockMenu.h +66 -0
- package/ios/utils/ENRMChipDrawing.h +24 -0
- package/ios/utils/ENRMChipDrawing.m +83 -0
- package/ios/utils/ENRMCodeBlockContent.h +37 -0
- package/ios/utils/ENRMCodeBlockContent.mm +79 -0
- package/ios/utils/ENRMCodeBlockHighlighter.h +37 -0
- package/ios/utils/ENRMCodeBlockHighlighter.mm +51 -0
- package/ios/utils/ENRMFeatureFlags.h +7 -0
- package/ios/utils/ENRMImageDownloader.h +11 -1
- package/ios/utils/ENRMImageDownloader.m +60 -16
- package/ios/utils/ENRMLinkChip.h +70 -0
- package/ios/utils/ENRMLinkChip.m +213 -0
- package/ios/utils/ENRMLinkLayout.h +50 -0
- package/ios/utils/ENRMLinkLayout.m +45 -0
- package/ios/utils/ENRMLocalImageLoader.h +31 -0
- package/ios/utils/ENRMLocalImageLoader.m +68 -0
- package/ios/utils/ENRMMathFallback.h +26 -0
- package/ios/utils/ENRMMathFallback.m +18 -0
- package/ios/utils/ENRMSelectionChange.h +120 -0
- package/ios/utils/ENRMSelectionChange.m +282 -0
- package/ios/utils/ENRMTextViewSetup.h +35 -17
- package/ios/utils/EditMenuUtils+macOS.m +4 -1
- package/ios/utils/EditMenuUtils.h +35 -6
- package/ios/utils/EditMenuUtils.m +188 -11
- package/ios/utils/HTMLGenerator.m +2 -1
- package/ios/utils/ImageRequestHeaderUtils.h +35 -0
- package/ios/utils/LastElementUtils.h +1 -0
- package/ios/utils/ListMarkerDrawer.m +29 -42
- package/ios/utils/MarkdownASTSerializer.m +4 -0
- package/ios/utils/MarkdownAccessibilityElementBuilder.m +3 -1
- package/ios/utils/MarkdownExtractor.m +2 -1
- package/ios/utils/ParagraphStyleUtils.h +5 -0
- package/ios/utils/ParagraphStyleUtils.m +77 -17
- package/ios/utils/RTFExportUtils.m +2 -0
- package/ios/utils/RenderedMarkdownSegment.h +13 -1
- package/ios/utils/RenderedMarkdownSegment.m +20 -0
- package/ios/utils/SegmentRenderer.m +17 -4
- package/ios/utils/StreamingMarkdownFilter.h +11 -1
- package/ios/utils/StreamingMarkdownFilter.m +98 -2
- package/ios/utils/StylePropsUtils.h +110 -1
- package/ios/utils/TaskListTapUtils.m +24 -0
- package/ios/utils/TextViewLayoutManager.mm +3 -0
- package/ios/views/ENRMCodeBlockContainerView.h +60 -0
- package/ios/views/ENRMCodeBlockContainerView.m +569 -0
- package/ios/views/ENRMMathContainerView.h +23 -0
- package/ios/views/ENRMMathContainerView.m +87 -20
- package/ios/views/TableContainerView.h +32 -0
- package/ios/views/TableContainerView.m +291 -175
- package/jest.d.ts +1 -0
- package/jest.js +5 -0
- package/lib/module/EnrichedMarkdownNativeComponent.ts +203 -1
- package/lib/module/EnrichedMarkdownTextInput.js +84 -5
- package/lib/module/EnrichedMarkdownTextInput.js.map +1 -1
- package/lib/module/EnrichedMarkdownTextInputNativeComponent.ts +78 -5
- package/lib/module/EnrichedMarkdownTextNativeComponent.ts +204 -1
- package/lib/module/headingDefaults.js +34 -0
- package/lib/module/headingDefaults.js.map +1 -0
- package/lib/module/index.js.map +1 -1
- package/lib/module/jest/index.js +205 -0
- package/lib/module/jest/index.js.map +1 -0
- package/lib/module/native/EnrichedMarkdownText.js +199 -15
- package/lib/module/native/EnrichedMarkdownText.js.map +1 -1
- package/lib/module/normalizeMarkdownStyle.js +98 -23
- package/lib/module/normalizeMarkdownStyle.js.map +1 -1
- package/lib/module/normalizeMarkdownStyle.web.js +73 -22
- package/lib/module/normalizeMarkdownStyle.web.js.map +1 -1
- package/lib/module/normalizeMarkdownTextInputStyle.js +62 -15
- package/lib/module/normalizeMarkdownTextInputStyle.js.map +1 -1
- package/lib/module/normalizeMenuItem.js +1 -1
- package/lib/module/utils/textInputState.js +26 -0
- package/lib/module/utils/textInputState.js.map +1 -0
- package/lib/module/web/EnrichedMarkdownText.js +15 -8
- package/lib/module/web/EnrichedMarkdownText.js.map +1 -1
- package/lib/module/web/parseMarkdown.js +4 -3
- package/lib/module/web/parseMarkdown.js.map +1 -1
- package/lib/module/web/renderers/InlineRenderers.js +102 -3
- package/lib/module/web/renderers/InlineRenderers.js.map +1 -1
- package/lib/module/web/renderers/ListRenderers.js +7 -2
- package/lib/module/web/renderers/ListRenderers.js.map +1 -1
- package/lib/module/web/renderers/index.js +7 -4
- package/lib/module/web/renderers/index.js.map +1 -1
- package/lib/module/web/styles.js +101 -6
- package/lib/module/web/styles.js.map +1 -1
- package/lib/module/web/utils.js +14 -0
- package/lib/module/web/utils.js.map +1 -1
- package/lib/module/web/wasm/md4c.js +0 -0
- package/lib/module/web/wasm/md4c.js.map +1 -1
- package/lib/typescript/src/EnrichedMarkdownNativeComponent.d.ts +185 -2
- package/lib/typescript/src/EnrichedMarkdownNativeComponent.d.ts.map +1 -1
- package/lib/typescript/src/EnrichedMarkdownTextInput.d.ts +94 -9
- package/lib/typescript/src/EnrichedMarkdownTextInput.d.ts.map +1 -1
- package/lib/typescript/src/EnrichedMarkdownTextInputNativeComponent.d.ts +69 -5
- package/lib/typescript/src/EnrichedMarkdownTextInputNativeComponent.d.ts.map +1 -1
- package/lib/typescript/src/EnrichedMarkdownTextNativeComponent.d.ts +185 -2
- package/lib/typescript/src/EnrichedMarkdownTextNativeComponent.d.ts.map +1 -1
- package/lib/typescript/src/headingDefaults.d.ts +9 -0
- package/lib/typescript/src/headingDefaults.d.ts.map +1 -0
- package/lib/typescript/src/index.d.ts +3 -3
- package/lib/typescript/src/index.d.ts.map +1 -1
- package/lib/typescript/src/index.web.d.ts +2 -2
- package/lib/typescript/src/index.web.d.ts.map +1 -1
- package/lib/typescript/src/jest/index.d.ts +6 -0
- package/lib/typescript/src/jest/index.d.ts.map +1 -0
- package/lib/typescript/src/native/EnrichedMarkdownText.d.ts +5 -5
- package/lib/typescript/src/native/EnrichedMarkdownText.d.ts.map +1 -1
- package/lib/typescript/src/normalizeMarkdownStyle.d.ts.map +1 -1
- package/lib/typescript/src/normalizeMarkdownStyle.web.d.ts.map +1 -1
- package/lib/typescript/src/normalizeMarkdownTextInputStyle.d.ts +19 -5
- package/lib/typescript/src/normalizeMarkdownTextInputStyle.d.ts.map +1 -1
- package/lib/typescript/src/types/MarkdownStyle.d.ts +122 -5
- package/lib/typescript/src/types/MarkdownStyle.d.ts.map +1 -1
- package/lib/typescript/src/types/MarkdownStyleInternal.d.ts +39 -0
- package/lib/typescript/src/types/MarkdownStyleInternal.d.ts.map +1 -1
- package/lib/typescript/src/types/MarkdownTextProps.d.ts +207 -10
- package/lib/typescript/src/types/MarkdownTextProps.d.ts.map +1 -1
- package/lib/typescript/src/types/MarkdownTextProps.web.d.ts +60 -1
- package/lib/typescript/src/types/MarkdownTextProps.web.d.ts.map +1 -1
- package/lib/typescript/src/types/events.d.ts +85 -0
- package/lib/typescript/src/types/events.d.ts.map +1 -1
- package/lib/typescript/src/utils/textInputState.d.ts +24 -0
- package/lib/typescript/src/utils/textInputState.d.ts.map +1 -0
- package/lib/typescript/src/web/EnrichedMarkdownText.d.ts +1 -1
- package/lib/typescript/src/web/EnrichedMarkdownText.d.ts.map +1 -1
- package/lib/typescript/src/web/parseMarkdown.d.ts +1 -1
- package/lib/typescript/src/web/parseMarkdown.d.ts.map +1 -1
- package/lib/typescript/src/web/renderers/InlineRenderers.d.ts.map +1 -1
- package/lib/typescript/src/web/renderers/ListRenderers.d.ts.map +1 -1
- package/lib/typescript/src/web/renderers/index.d.ts +2 -1
- package/lib/typescript/src/web/renderers/index.d.ts.map +1 -1
- package/lib/typescript/src/web/styles.d.ts +2 -1
- package/lib/typescript/src/web/styles.d.ts.map +1 -1
- package/lib/typescript/src/web/types.d.ts +10 -2
- package/lib/typescript/src/web/types.d.ts.map +1 -1
- package/lib/typescript/src/web/utils.d.ts +4 -0
- package/lib/typescript/src/web/utils.d.ts.map +1 -1
- package/package.json +36 -9
- package/postinstall.mjs +131 -0
- package/ratex-version.json +21 -0
- package/src/EnrichedMarkdownNativeComponent.ts +203 -1
- package/src/EnrichedMarkdownTextInput.tsx +159 -8
- package/src/EnrichedMarkdownTextInputNativeComponent.ts +78 -5
- package/src/EnrichedMarkdownTextNativeComponent.ts +204 -1
- package/src/headingDefaults.ts +21 -0
- package/src/index.tsx +15 -0
- package/src/index.web.tsx +6 -1
- package/src/jest/index.tsx +236 -0
- package/src/native/EnrichedMarkdownText.tsx +260 -11
- package/src/normalizeMarkdownStyle.ts +117 -16
- package/src/normalizeMarkdownStyle.web.ts +76 -15
- package/src/normalizeMarkdownTextInputStyle.ts +110 -35
- package/src/normalizeMenuItem.ts +1 -1
- package/src/types/MarkdownStyle.ts +125 -5
- package/src/types/MarkdownStyleInternal.ts +51 -0
- package/src/types/MarkdownTextProps.ts +215 -10
- package/src/types/MarkdownTextProps.web.ts +62 -1
- package/src/types/events.ts +90 -0
- package/src/utils/textInputState.ts +35 -0
- package/src/web/EnrichedMarkdownText.tsx +26 -5
- package/src/web/parseMarkdown.ts +6 -2
- package/src/web/renderers/InlineRenderers.tsx +116 -3
- package/src/web/renderers/ListRenderers.tsx +14 -2
- package/src/web/renderers/index.tsx +6 -2
- package/src/web/styles.ts +114 -5
- package/src/web/types.ts +10 -1
- package/src/web/utils.ts +9 -0
- package/src/web/wasm/md4c.js +0 -0
- package/vendor-grammars.mjs +511 -0
- package/vendor-ratex.mjs +173 -0
- package/app.plugin.js +0 -2
- package/plugin/build/withAndroidMath.js +0 -19
- package/plugin/build/withIosMath.js +0 -28
- package/plugin/build/withReactNativeEnrichedMarkdown.js +0 -11
- package/plugin/src/withAndroidMath.ts +0 -24
- package/plugin/src/withIosMath.ts +0 -35
- package/plugin/src/withReactNativeEnrichedMarkdown.ts +0 -17
- package/plugin/tsconfig.build.json +0 -16
package/ios/EnrichedMarkdown.mm
CHANGED
|
@@ -2,6 +2,7 @@
|
|
|
2
2
|
#import "ContextMenuUtils.h"
|
|
3
3
|
#import "ENRMAccessibilityLabels.h"
|
|
4
4
|
#import "ENRMAsyncRenderCoordinator.h"
|
|
5
|
+
#import "ENRMAtomicSize.h"
|
|
5
6
|
#import "ENRMImageAttachment.h"
|
|
6
7
|
#import "ENRMMarkdownParser.h"
|
|
7
8
|
#import "ENRMTailFadeInAnimator.h"
|
|
@@ -10,12 +11,16 @@
|
|
|
10
11
|
#import "ENRMTextViewSetup.h"
|
|
11
12
|
#import "ENRMUIKit.h"
|
|
12
13
|
#import "EditMenuUtils.h"
|
|
14
|
+
#import "ImageRequestHeaderUtils.h"
|
|
13
15
|
|
|
14
16
|
#import "ENRMFeatureFlags.h"
|
|
15
17
|
|
|
16
18
|
#if ENRICHED_MARKDOWN_MATH
|
|
17
19
|
#import "ENRMMathContainerView.h"
|
|
18
20
|
#endif
|
|
21
|
+
#import "ENRMCodeBlockContainerView.h"
|
|
22
|
+
#import "ENRMLinkLayout.h"
|
|
23
|
+
#import "ENRMSelectionChange.h"
|
|
19
24
|
#import "ENRMSpoilerCapable.h"
|
|
20
25
|
#import "ENRMSpoilerOverlayView.h"
|
|
21
26
|
#import "ENRMSpoilerTapUtils.h"
|
|
@@ -66,10 +71,14 @@ typedef NS_OPTIONS(NSUInteger, ENRMDirtyFlags) {
|
|
|
66
71
|
|
|
67
72
|
static char kENRMSegmentFadeAnimatorKey;
|
|
68
73
|
|
|
69
|
-
@interface EnrichedMarkdown () <RCTEnrichedMarkdownViewProtocol, UITextViewDelegate>
|
|
74
|
+
@interface EnrichedMarkdown () <RCTEnrichedMarkdownViewProtocol, UITextViewDelegate, ENRMImageLayoutObserver>
|
|
75
|
+
+ (ENRMMd4cFlags *)flagsFromProps:(const EnrichedMarkdownMd4cFlagsStruct &)props;
|
|
70
76
|
- (void)emitLinkPress:(NSString *)url;
|
|
71
77
|
- (void)emitLinkLongPress:(NSString *)url;
|
|
78
|
+
- (void)emitLinkLayoutIfNeeded;
|
|
72
79
|
- (void)emitTaskListItemPress:(NSInteger)index checked:(BOOL)checked text:(NSString *)text;
|
|
80
|
+
- (void)emitCopyPress:(NSString *)code language:(NSString *)language;
|
|
81
|
+
- (void)emitCopyRequest:(NSString *)source markdown:(NSString *)markdown text:(NSString *)text whole:(BOOL)whole;
|
|
73
82
|
- (void)emitContextMenuItemPress:(NSString *)itemText
|
|
74
83
|
selectedText:(NSString *)selectedText
|
|
75
84
|
selectionStart:(NSUInteger)selectionStart
|
|
@@ -98,8 +107,14 @@ static char kENRMSegmentFadeAnimatorKey;
|
|
|
98
107
|
BOOL _allowTrailingMargin;
|
|
99
108
|
BOOL _selectable;
|
|
100
109
|
BOOL _enableLinkPreview;
|
|
110
|
+
BOOL _linkLongPressSelects;
|
|
111
|
+
BOOL _enableTaskListItemToggle;
|
|
112
|
+
BOOL _contextMenuHidden;
|
|
101
113
|
BOOL _streamingAnimation;
|
|
102
114
|
ENRMTableStreamingMode _tableStreamingMode;
|
|
115
|
+
ENRMCodeBlockStreamingMode _codeBlockStreamingMode;
|
|
116
|
+
// Trailing code block whose closing fence hasn't streamed in yet, if any.
|
|
117
|
+
ENRMCodeBlockSegment *_pendingCodeBlockSegment;
|
|
103
118
|
|
|
104
119
|
size_t _renderedStyleFingerprint;
|
|
105
120
|
size_t _pendingStyleFingerprint;
|
|
@@ -112,10 +127,27 @@ static char kENRMSegmentFadeAnimatorKey;
|
|
|
112
127
|
|
|
113
128
|
ENRMSpoilerOverlay _spoilerOverlay;
|
|
114
129
|
|
|
130
|
+
BOOL _emitLinkLayout;
|
|
131
|
+
NSArray<NSDictionary *> *_lastLinkLayout;
|
|
132
|
+
|
|
133
|
+
ENRMSelectionChangeReporter *_selectionReporter;
|
|
134
|
+
#if !TARGET_OS_OSX
|
|
135
|
+
ENRMSelectionGestureTracker *_selectionGestures;
|
|
136
|
+
#endif
|
|
137
|
+
// At most one segment holds a selection; a new one clears the previous.
|
|
138
|
+
__weak ENRMPlatformTextView *_selectionOwner;
|
|
139
|
+
// A block long-pressed while contextMenuHidden is on, reported as the selection.
|
|
140
|
+
__weak RCTUIView *_activeBlockView;
|
|
141
|
+
NSString *_activeBlockSource;
|
|
142
|
+
NSString *_activeBlockMarkdown;
|
|
143
|
+
NSString *_activeBlockText;
|
|
144
|
+
|
|
115
145
|
NSLineBreakStrategy _lineBreakStrategy;
|
|
116
146
|
|
|
117
147
|
ENRMWritingDirectionMode _writingDirectionMode;
|
|
118
148
|
NSWritingDirection _resolvedLayoutDirection;
|
|
149
|
+
|
|
150
|
+
ENRMAtomicSize _lastCommittedSize;
|
|
119
151
|
}
|
|
120
152
|
|
|
121
153
|
+ (ComponentDescriptorProvider)componentDescriptorProvider
|
|
@@ -123,43 +155,16 @@ static char kENRMSegmentFadeAnimatorKey;
|
|
|
123
155
|
return concreteComponentDescriptorProvider<EnrichedMarkdownComponentDescriptor>();
|
|
124
156
|
}
|
|
125
157
|
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
/// Requires `_fontScaleObserver` to already exist.
|
|
137
|
-
- (void)resetPropDerivedState
|
|
138
|
-
{
|
|
139
|
-
// Discarded rather than cleared field-by-field: the style diff can only clear a
|
|
140
|
-
// field when new and old differ, which never holds against a reset baseline.
|
|
141
|
-
_config = nil;
|
|
142
|
-
|
|
143
|
-
_md4cFlags = [ENRMMd4cFlags propsDefaultFlags];
|
|
144
|
-
_maxFontSizeMultiplier = 0;
|
|
145
|
-
_allowTrailingMargin = NO;
|
|
146
|
-
_fontScaleObserver.allowFontScaling = YES;
|
|
147
|
-
_streamingAnimation = NO;
|
|
148
|
-
_tableStreamingMode = ENRMTableStreamingModeProgressive;
|
|
149
|
-
_spoilerOverlay = ENRMSpoilerOverlayParticles;
|
|
150
|
-
_lineBreakStrategy = NSLineBreakStrategyNone;
|
|
151
|
-
_writingDirectionMode = ENRMWritingDirectionModeFirstStrong;
|
|
152
|
-
_contextMenuItemTexts = nil;
|
|
153
|
-
_contextMenuItemIcons = nil;
|
|
154
|
-
_accessibilityLabels = nil;
|
|
155
|
-
|
|
156
|
-
// Written only once a render completes, so stale until the next one lands.
|
|
157
|
-
_renderedStyleFingerprint = 0;
|
|
158
|
-
_pendingStyleFingerprint = 0;
|
|
159
|
-
|
|
160
|
-
_dirtyFlags = ENRMDirtyNone;
|
|
161
|
-
_heightUpdateCounter = 0;
|
|
162
|
-
_state = nullptr;
|
|
158
|
+
+ (ENRMMd4cFlags *)flagsFromProps:(const EnrichedMarkdownMd4cFlagsStruct &)props
|
|
159
|
+
{
|
|
160
|
+
ENRMMd4cFlags *flags = [ENRMMd4cFlags defaultFlags];
|
|
161
|
+
flags.underline = props.underline;
|
|
162
|
+
flags.superscript = props.superscript;
|
|
163
|
+
flags.subscript = props.subscript;
|
|
164
|
+
flags.latexMath = props.latexMath;
|
|
165
|
+
flags.highlight = props.highlight;
|
|
166
|
+
flags.hardSoftBreaks = props.hardSoftBreaks;
|
|
167
|
+
return flags;
|
|
163
168
|
}
|
|
164
169
|
|
|
165
170
|
- (instancetype)initWithFrame:(CGRect)frame
|
|
@@ -170,22 +175,31 @@ static char kENRMSegmentFadeAnimatorKey;
|
|
|
170
175
|
|
|
171
176
|
self.backgroundColor = [RCTUIColor clearColor];
|
|
172
177
|
_parser = [[ENRMMarkdownParser alloc] init];
|
|
178
|
+
_md4cFlags = [EnrichedMarkdown flagsFromProps:defaultProps->md4cFlags];
|
|
173
179
|
_segmentViews = [NSMutableArray array];
|
|
174
180
|
_segmentSignatures = [NSMutableArray array];
|
|
181
|
+
_dirtyFlags = ENRMDirtyNone;
|
|
175
182
|
[self configureSegmentViewRegistry];
|
|
176
183
|
|
|
177
184
|
_renderCoordinator =
|
|
178
185
|
[[ENRMAsyncRenderCoordinator alloc] initWithQueueLabel:"com.swmansion.enriched.markdown.container.render"];
|
|
179
186
|
|
|
187
|
+
_maxFontSizeMultiplier = 0;
|
|
188
|
+
_allowTrailingMargin = NO;
|
|
180
189
|
_selectable = YES;
|
|
181
190
|
_enableLinkPreview = YES;
|
|
182
|
-
|
|
191
|
+
_enableTaskListItemToggle = YES;
|
|
192
|
+
_streamingAnimation = NO;
|
|
193
|
+
_tableStreamingMode = ENRMTableStreamingModeProgressive;
|
|
194
|
+
_codeBlockStreamingMode = ENRMCodeBlockStreamingModeProgressive;
|
|
195
|
+
_contextMenuHidden = NO;
|
|
196
|
+
_selectionMenuConfig = ENRMDefaultSelectionMenuConfig();
|
|
197
|
+
_lineBreakStrategy = NSLineBreakStrategyNone;
|
|
198
|
+
_writingDirectionMode = ENRMWritingDirectionModeFirstStrong;
|
|
183
199
|
_resolvedLayoutDirection =
|
|
184
200
|
[[RCTI18nUtil sharedInstance] isRTL] ? NSWritingDirectionRightToLeft : NSWritingDirectionLeftToRight;
|
|
185
201
|
|
|
186
202
|
_fontScaleObserver = [[FontScaleObserver alloc] init];
|
|
187
|
-
[self resetPropDerivedState];
|
|
188
|
-
|
|
189
203
|
__weak EnrichedMarkdown *weakSelf = self;
|
|
190
204
|
_fontScaleObserver.onChange = ^{
|
|
191
205
|
EnrichedMarkdown *strongSelf = weakSelf;
|
|
@@ -199,10 +213,132 @@ static char kENRMSegmentFadeAnimatorKey;
|
|
|
199
213
|
[strongSelf renderMarkdownContent:strongSelf->_cachedMarkdown];
|
|
200
214
|
}
|
|
201
215
|
};
|
|
216
|
+
|
|
217
|
+
_selectionReporter = [[ENRMSelectionChangeReporter alloc]
|
|
218
|
+
initWithSnapshot:^NSDictionary * {
|
|
219
|
+
EnrichedMarkdown *strongSelf = weakSelf;
|
|
220
|
+
return strongSelf ? [strongSelf selectionPayload] : ENRMInactiveSelectionPayload();
|
|
221
|
+
}
|
|
222
|
+
emit:^(NSDictionary *payload) {
|
|
223
|
+
EnrichedMarkdown *strongSelf = weakSelf;
|
|
224
|
+
if (!strongSelf)
|
|
225
|
+
return;
|
|
226
|
+
auto emitter = std::static_pointer_cast<EnrichedMarkdownEventEmitter const>(strongSelf->_eventEmitter);
|
|
227
|
+
if (emitter)
|
|
228
|
+
emitter->onSelectionChange(
|
|
229
|
+
ENRMSelectionChangeEventFromPayload<EnrichedMarkdownEventEmitter::OnSelectionChange>(payload));
|
|
230
|
+
}];
|
|
231
|
+
#if !TARGET_OS_OSX
|
|
232
|
+
// A handle drag starting or ending is reported right away, even when the
|
|
233
|
+
// selection itself is unchanged.
|
|
234
|
+
_selectionGestures = [[ENRMSelectionGestureTracker alloc] initWithChange:^{
|
|
235
|
+
EnrichedMarkdown *strongSelf = weakSelf;
|
|
236
|
+
if (!strongSelf)
|
|
237
|
+
return;
|
|
238
|
+
UITextView *owner = strongSelf->_selectionOwner;
|
|
239
|
+
if (owner)
|
|
240
|
+
[strongSelf->_selectionGestures trackTextView:owner];
|
|
241
|
+
[strongSelf->_selectionReporter forgetLastReported];
|
|
242
|
+
[strongSelf->_selectionReporter flushNow];
|
|
243
|
+
}];
|
|
244
|
+
#endif
|
|
202
245
|
}
|
|
203
246
|
return self;
|
|
204
247
|
}
|
|
205
248
|
|
|
249
|
+
#pragma mark - Selection
|
|
250
|
+
|
|
251
|
+
/// The current selection (or active block) as an `onSelectionChange` payload.
|
|
252
|
+
/// Markdown and `whole` follow the same rules as the intercepted Copy.
|
|
253
|
+
- (NSDictionary *)selectionPayload
|
|
254
|
+
{
|
|
255
|
+
RCTUIView *blockView = _activeBlockView;
|
|
256
|
+
if (blockView != nil) {
|
|
257
|
+
if (blockView.superview != self)
|
|
258
|
+
return ENRMInactiveSelectionPayload();
|
|
259
|
+
return ENRMBlockSelectionPayload(_activeBlockSource, _activeBlockMarkdown, _activeBlockText, blockView.frame);
|
|
260
|
+
}
|
|
261
|
+
|
|
262
|
+
#if !TARGET_OS_OSX
|
|
263
|
+
UITextView *owner = _selectionOwner;
|
|
264
|
+
if (owner == nil || ![owner isDescendantOfView:self])
|
|
265
|
+
return ENRMInactiveSelectionPayload();
|
|
266
|
+
NSDictionary *selection = ENRMTextSelectionInTextView(owner, self);
|
|
267
|
+
if (!selection)
|
|
268
|
+
return ENRMInactiveSelectionPayload();
|
|
269
|
+
|
|
270
|
+
NSString *text = selection[ENRMSelectionTextKey];
|
|
271
|
+
// Segments only see their own text, so a selection is the whole component
|
|
272
|
+
// only when it spans the sole segment; the markdown is then the original.
|
|
273
|
+
BOOL whole = [selection[ENRMSelectionFullKey] boolValue] && _segmentViews.count == 1 && _cachedMarkdown.length > 0;
|
|
274
|
+
NSString *markdown =
|
|
275
|
+
whole ? _cachedMarkdown : extractMarkdownFromAttributedString(owner.attributedText, owner.selectedRange);
|
|
276
|
+
NSMutableDictionary *payload = [selection mutableCopy];
|
|
277
|
+
[payload removeObjectForKey:ENRMSelectionFullKey];
|
|
278
|
+
payload[ENRMSelectionActiveKey] = @YES;
|
|
279
|
+
payload[ENRMSelectionSourceKey] = @"selection";
|
|
280
|
+
payload[ENRMSelectionMarkdownKey] = markdown.length > 0 ? markdown : text;
|
|
281
|
+
payload[ENRMSelectionWholeKey] = @(whole);
|
|
282
|
+
payload[ENRMSelectionAdjustingKey] = @(_selectionGestures.adjusting);
|
|
283
|
+
return payload;
|
|
284
|
+
#else
|
|
285
|
+
return ENRMInactiveSelectionPayload();
|
|
286
|
+
#endif
|
|
287
|
+
}
|
|
288
|
+
|
|
289
|
+
- (void)clearActiveBlock
|
|
290
|
+
{
|
|
291
|
+
_activeBlockView = nil;
|
|
292
|
+
_activeBlockSource = nil;
|
|
293
|
+
_activeBlockMarkdown = nil;
|
|
294
|
+
_activeBlockText = nil;
|
|
295
|
+
}
|
|
296
|
+
|
|
297
|
+
- (void)clearSegmentSelection:(ENRMPlatformTextView *)textView
|
|
298
|
+
{
|
|
299
|
+
#if !TARGET_OS_OSX
|
|
300
|
+
textView.selectedRange = NSMakeRange(0, 0);
|
|
301
|
+
[textView resignFirstResponder];
|
|
302
|
+
#endif
|
|
303
|
+
}
|
|
304
|
+
|
|
305
|
+
- (void)clearSelection
|
|
306
|
+
{
|
|
307
|
+
ENRMPlatformTextView *owner = _selectionOwner;
|
|
308
|
+
_selectionOwner = nil;
|
|
309
|
+
[self clearActiveBlock];
|
|
310
|
+
if (owner)
|
|
311
|
+
[self clearSegmentSelection:owner];
|
|
312
|
+
[_selectionReporter flushNow];
|
|
313
|
+
}
|
|
314
|
+
|
|
315
|
+
- (void)handleCommand:(const NSString *)commandName args:(const NSArray *)args
|
|
316
|
+
{
|
|
317
|
+
RCTEnrichedMarkdownHandleCommand(self, commandName, args);
|
|
318
|
+
}
|
|
319
|
+
|
|
320
|
+
- (ENRMBlockCopyRequestBlock)blockMenuSuppressedForSource:(NSString *)source view:(RCTUIView *)view
|
|
321
|
+
{
|
|
322
|
+
__weak EnrichedMarkdown *weakSelf = self;
|
|
323
|
+
__weak RCTUIView *weakView = view;
|
|
324
|
+
return ^(NSString *markdown, NSString *text) {
|
|
325
|
+
EnrichedMarkdown *strongSelf = weakSelf;
|
|
326
|
+
RCTUIView *strongView = weakView;
|
|
327
|
+
if (!strongSelf || !strongView || !strongSelf->_selectionReporter.enabled)
|
|
328
|
+
return;
|
|
329
|
+
ENRMPlatformTextView *owner = strongSelf->_selectionOwner;
|
|
330
|
+
strongSelf->_selectionOwner = nil;
|
|
331
|
+
if (owner)
|
|
332
|
+
[strongSelf clearSegmentSelection:owner];
|
|
333
|
+
strongSelf->_activeBlockView = strongView;
|
|
334
|
+
strongSelf->_activeBlockSource = source;
|
|
335
|
+
strongSelf->_activeBlockMarkdown = markdown;
|
|
336
|
+
strongSelf->_activeBlockText = text;
|
|
337
|
+
[strongSelf->_selectionReporter forgetLastReported];
|
|
338
|
+
[strongSelf->_selectionReporter flushNow];
|
|
339
|
+
};
|
|
340
|
+
}
|
|
341
|
+
|
|
206
342
|
- (void)configureSegmentViewRegistry
|
|
207
343
|
{
|
|
208
344
|
__weak EnrichedMarkdown *weakSelf = self;
|
|
@@ -273,6 +409,29 @@ static char kENRMSegmentFadeAnimatorKey;
|
|
|
273
409
|
}]];
|
|
274
410
|
#endif
|
|
275
411
|
|
|
412
|
+
[handlers addObject:[ENRMSegmentViewHandler handlerWithKind:ENRMSegmentKindCodeBlock
|
|
413
|
+
matchesView:^BOOL(RCTUIView *view, ENRMRenderedSegment *segment) {
|
|
414
|
+
return [view isKindOfClass:[ENRMCodeBlockContainerView class]];
|
|
415
|
+
}
|
|
416
|
+
createView:^RCTUIView *(ENRMRenderedSegment *segment) {
|
|
417
|
+
EnrichedMarkdown *strongSelf = weakSelf;
|
|
418
|
+
if (!strongSelf) {
|
|
419
|
+
return [[RCTUIView alloc] init];
|
|
420
|
+
}
|
|
421
|
+
|
|
422
|
+
ENRMCodeBlockContainerView *view =
|
|
423
|
+
[strongSelf createCodeBlockViewForSegment:segment.codeBlockSegment];
|
|
424
|
+
[strongSelf animateBlockViewIfNeeded:view];
|
|
425
|
+
return view;
|
|
426
|
+
}
|
|
427
|
+
updateView:^(RCTUIView *view, ENRMRenderedSegment *segment) {
|
|
428
|
+
EnrichedMarkdown *strongSelf = weakSelf;
|
|
429
|
+
ENRMCodeBlockContainerView *codeBlockView = (ENRMCodeBlockContainerView *)view;
|
|
430
|
+
codeBlockView.pending =
|
|
431
|
+
strongSelf && segment.codeBlockSegment == strongSelf->_pendingCodeBlockSegment;
|
|
432
|
+
[codeBlockView applyCodeBlockNode:segment.codeBlockSegment.codeBlockNode];
|
|
433
|
+
}]];
|
|
434
|
+
|
|
276
435
|
_segmentViewRegistry = [[ENRMSegmentViewRegistry alloc] initWithHandlers:handlers];
|
|
277
436
|
}
|
|
278
437
|
|
|
@@ -281,6 +440,29 @@ static char kENRMSegmentFadeAnimatorKey;
|
|
|
281
440
|
if (_segmentViews.count == 0)
|
|
282
441
|
return CGSizeZero;
|
|
283
442
|
|
|
443
|
+
if (applyFrames) {
|
|
444
|
+
CGFloat overhang = MAX(_config.tableHorizontalOverflow, 0);
|
|
445
|
+
BOOL needsOverhang = NO;
|
|
446
|
+
if (overhang > 0) {
|
|
447
|
+
for (RCTUIView *seg in _segmentViews) {
|
|
448
|
+
if ([seg isKindOfClass:[TableContainerView class]]) {
|
|
449
|
+
needsOverhang = YES;
|
|
450
|
+
break;
|
|
451
|
+
}
|
|
452
|
+
}
|
|
453
|
+
}
|
|
454
|
+
#if TARGET_OS_OSX
|
|
455
|
+
BOOL isClipping = self.layer.masksToBounds;
|
|
456
|
+
if (isClipping && needsOverhang)
|
|
457
|
+
self.layer.masksToBounds = NO;
|
|
458
|
+
else if (!isClipping && !needsOverhang)
|
|
459
|
+
self.layer.masksToBounds = YES;
|
|
460
|
+
#else
|
|
461
|
+
if (self.clipsToBounds != !needsOverhang)
|
|
462
|
+
self.clipsToBounds = !needsOverhang;
|
|
463
|
+
#endif
|
|
464
|
+
}
|
|
465
|
+
|
|
284
466
|
__block CGFloat yOffset = 0.0;
|
|
285
467
|
__block CGFloat maxContentWidth = 0.0;
|
|
286
468
|
const NSUInteger lastIndex = _segmentViews.count - 1;
|
|
@@ -290,6 +472,7 @@ static char kENRMSegmentFadeAnimatorKey;
|
|
|
290
472
|
const BOOL shouldAddBottomMargin = (!isLast || _allowTrailingMargin);
|
|
291
473
|
|
|
292
474
|
CGFloat segmentHeight = 0;
|
|
475
|
+
const BOOL isTable = [segment isKindOfClass:[TableContainerView class]];
|
|
293
476
|
|
|
294
477
|
if ([segment isKindOfClass:[EnrichedMarkdownInternalText class]]) {
|
|
295
478
|
EnrichedMarkdownInternalText *textView = (EnrichedMarkdownInternalText *)segment;
|
|
@@ -298,7 +481,7 @@ static char kENRMSegmentFadeAnimatorKey;
|
|
|
298
481
|
segmentHeight = textSize.height;
|
|
299
482
|
maxContentWidth = MAX(maxContentWidth, textSize.width);
|
|
300
483
|
|
|
301
|
-
} else if (
|
|
484
|
+
} else if (isTable) {
|
|
302
485
|
yOffset += _config.tableMarginTop;
|
|
303
486
|
segmentHeight = [(TableContainerView *)segment measureHeight:width];
|
|
304
487
|
maxContentWidth = width;
|
|
@@ -310,9 +493,23 @@ static char kENRMSegmentFadeAnimatorKey;
|
|
|
310
493
|
maxContentWidth = width;
|
|
311
494
|
}
|
|
312
495
|
#endif
|
|
496
|
+
else if ([segment isKindOfClass:[ENRMCodeBlockContainerView class]]) {
|
|
497
|
+
yOffset += _config.codeBlockMarginTop;
|
|
498
|
+
segmentHeight = [(ENRMCodeBlockContainerView *)segment measureHeight:width];
|
|
499
|
+
maxContentWidth = width;
|
|
500
|
+
}
|
|
313
501
|
|
|
314
502
|
if (applyFrames) {
|
|
315
|
-
|
|
503
|
+
CGFloat segmentX = 0;
|
|
504
|
+
CGFloat segmentWidth = width;
|
|
505
|
+
if (isTable) {
|
|
506
|
+
CGFloat overhang = MAX(_config.tableHorizontalOverflow, 0);
|
|
507
|
+
if (overhang > 0) {
|
|
508
|
+
segmentX = -overhang;
|
|
509
|
+
segmentWidth = width + overhang * 2;
|
|
510
|
+
}
|
|
511
|
+
}
|
|
512
|
+
CGRect segmentFrame = CGRectMake(segmentX, yOffset, segmentWidth, segmentHeight);
|
|
316
513
|
segment.frame = segmentFrame;
|
|
317
514
|
#if TARGET_OS_OSX
|
|
318
515
|
if ([segment isKindOfClass:[EnrichedMarkdownInternalText class]]) {
|
|
@@ -335,6 +532,9 @@ static char kENRMSegmentFadeAnimatorKey;
|
|
|
335
532
|
yOffset += _config.mathMarginBottom;
|
|
336
533
|
}
|
|
337
534
|
#endif
|
|
535
|
+
else if ([segment isKindOfClass:[ENRMCodeBlockContainerView class]] && shouldAddBottomMargin) {
|
|
536
|
+
yOffset += _config.codeBlockMarginBottom;
|
|
537
|
+
}
|
|
338
538
|
}];
|
|
339
539
|
|
|
340
540
|
return CGSizeMake(maxContentWidth, yOffset);
|
|
@@ -353,6 +553,11 @@ static char kENRMSegmentFadeAnimatorKey;
|
|
|
353
553
|
return CGSizeMake(measuredWidth, measuredHeight);
|
|
354
554
|
}
|
|
355
555
|
|
|
556
|
+
- (CGSize)lastCommittedLayoutSize
|
|
557
|
+
{
|
|
558
|
+
return _lastCommittedSize.load();
|
|
559
|
+
}
|
|
560
|
+
|
|
356
561
|
- (BOOL)hasRenderedMarkdown:(NSString *)markdown
|
|
357
562
|
{
|
|
358
563
|
return _renderedMarkdown != nil && [_renderedMarkdown isEqualToString:markdown];
|
|
@@ -396,6 +601,8 @@ static char kENRMSegmentFadeAnimatorKey;
|
|
|
396
601
|
{
|
|
397
602
|
[super updateLayoutMetrics:layoutMetrics oldLayoutMetrics:oldLayoutMetrics];
|
|
398
603
|
|
|
604
|
+
_lastCommittedSize.store(CGSizeMake(layoutMetrics.frame.size.width, layoutMetrics.frame.size.height));
|
|
605
|
+
|
|
399
606
|
NSWritingDirection resolved = _resolvedLayoutDirection;
|
|
400
607
|
if (layoutMetrics.layoutDirection == LayoutDirection::RightToLeft) {
|
|
401
608
|
resolved = NSWritingDirectionRightToLeft;
|
|
@@ -440,9 +647,30 @@ static char kENRMSegmentFadeAnimatorKey;
|
|
|
440
647
|
}
|
|
441
648
|
}
|
|
442
649
|
|
|
443
|
-
|
|
444
|
-
|
|
445
|
-
|
|
650
|
+
- (ENRMBlockMenuOptions)blockMenuOptions
|
|
651
|
+
{
|
|
652
|
+
return (ENRMBlockMenuOptions){
|
|
653
|
+
.copyHidden = !_selectionMenuConfig.copyEnabled,
|
|
654
|
+
.copyWritesMarkdown = _selectionMenuConfig.copyFormatMarkdown,
|
|
655
|
+
.copyAsMarkdownHidden = !_selectionMenuConfig.copyAsMarkdown,
|
|
656
|
+
.copyButtonHidden = !_selectionMenuConfig.codeBlockCopyButton,
|
|
657
|
+
.interceptCopy = _selectionMenuConfig.interceptCopy,
|
|
658
|
+
};
|
|
659
|
+
}
|
|
660
|
+
|
|
661
|
+
- (ENRMBlockCopyRequestBlock)blockCopyRequestForSource:(NSString *)source
|
|
662
|
+
{
|
|
663
|
+
__weak EnrichedMarkdown *weakSelf = self;
|
|
664
|
+
return ^(NSString *markdown, NSString *text) {
|
|
665
|
+
EnrichedMarkdown *strongSelf = weakSelf;
|
|
666
|
+
if (strongSelf)
|
|
667
|
+
[strongSelf emitCopyRequest:source markdown:markdown text:text whole:YES];
|
|
668
|
+
};
|
|
669
|
+
}
|
|
670
|
+
|
|
671
|
+
// Table, math and code block views cache the copy labels and menu options at
|
|
672
|
+
// creation time, so re-push them on prop updates (e.g. a language change
|
|
673
|
+
// without a remount) to avoid stale values.
|
|
446
674
|
- (void)pushSelectionMenuLabelsToSegments
|
|
447
675
|
{
|
|
448
676
|
for (RCTUIView *segment in _segmentViews) {
|
|
@@ -450,14 +678,25 @@ static char kENRMSegmentFadeAnimatorKey;
|
|
|
450
678
|
TableContainerView *tableView = (TableContainerView *)segment;
|
|
451
679
|
tableView.copyLabel = _selectionMenuLabels.copyLabel;
|
|
452
680
|
tableView.copyAsMarkdownLabel = _selectionMenuLabels.copyAsMarkdownLabel;
|
|
681
|
+
tableView.contextMenuHidden = _contextMenuHidden;
|
|
682
|
+
tableView.menuOptions = [self blockMenuOptions];
|
|
453
683
|
}
|
|
454
684
|
#if ENRICHED_MARKDOWN_MATH
|
|
455
685
|
else if ([segment isKindOfClass:[ENRMMathContainerView class]]) {
|
|
456
686
|
ENRMMathContainerView *mathView = (ENRMMathContainerView *)segment;
|
|
457
687
|
mathView.copyLabel = _selectionMenuLabels.copyLabel;
|
|
458
688
|
mathView.copyAsMarkdownLabel = _selectionMenuLabels.copyAsMarkdownLabel;
|
|
689
|
+
mathView.contextMenuHidden = _contextMenuHidden;
|
|
690
|
+
mathView.menuOptions = [self blockMenuOptions];
|
|
459
691
|
}
|
|
460
692
|
#endif
|
|
693
|
+
else if ([segment isKindOfClass:[ENRMCodeBlockContainerView class]]) {
|
|
694
|
+
ENRMCodeBlockContainerView *codeBlockView = (ENRMCodeBlockContainerView *)segment;
|
|
695
|
+
codeBlockView.copyLabel = _selectionMenuLabels.copyLabel;
|
|
696
|
+
codeBlockView.copyAsMarkdownLabel = _selectionMenuLabels.copyAsMarkdownLabel;
|
|
697
|
+
codeBlockView.contextMenuHidden = _contextMenuHidden;
|
|
698
|
+
codeBlockView.menuOptions = [self blockMenuOptions];
|
|
699
|
+
}
|
|
461
700
|
}
|
|
462
701
|
}
|
|
463
702
|
|
|
@@ -466,6 +705,25 @@ static char kENRMSegmentFadeAnimatorKey;
|
|
|
466
705
|
ENRMRequestHeightUpdate<EnrichedMarkdownState>(_state, _heightUpdateCounter, self);
|
|
467
706
|
}
|
|
468
707
|
|
|
708
|
+
// A block image in one of the text segments resolved its box height after
|
|
709
|
+
// loading (maxHeight/aspectRatio sizing). The shadow node measured — and
|
|
710
|
+
// cached — this markdown with the pre-load fallback height, so drop those
|
|
711
|
+
// entries, re-stack segments, and re-measure.
|
|
712
|
+
- (void)imageAttachmentDidResolveLayout
|
|
713
|
+
{
|
|
714
|
+
if (_renderedMarkdown.length > 0) {
|
|
715
|
+
MeasurementCache::shared().removeMatchingMarkdown(std::string(_renderedMarkdown.UTF8String));
|
|
716
|
+
}
|
|
717
|
+
|
|
718
|
+
if (self.bounds.size.width > 0) {
|
|
719
|
+
[self setNeedsLayout];
|
|
720
|
+
CGSize measured = [self measureSize:self.bounds.size.width];
|
|
721
|
+
if (needsHeightUpdate(measured, self.bounds)) {
|
|
722
|
+
[self requestHeightUpdate];
|
|
723
|
+
}
|
|
724
|
+
}
|
|
725
|
+
}
|
|
726
|
+
|
|
469
727
|
- (void)renderMarkdownContent:(NSString *)markdownString
|
|
470
728
|
{
|
|
471
729
|
if (_renderCoordinator.blockAsyncRender)
|
|
@@ -482,17 +740,21 @@ static char kENRMSegmentFadeAnimatorKey;
|
|
|
482
740
|
BOOL allowTrailingMargin = _allowTrailingMargin;
|
|
483
741
|
BOOL streamingAnimation = _streamingAnimation;
|
|
484
742
|
ENRMTableStreamingMode tableStreamingMode = _tableStreamingMode;
|
|
743
|
+
ENRMCodeBlockStreamingMode codeBlockStreamingMode = _codeBlockStreamingMode;
|
|
485
744
|
NSLineBreakStrategy lineBreakStrategy = _lineBreakStrategy;
|
|
486
745
|
ENRMWritingDirectionMode writingDirectionMode = _writingDirectionMode;
|
|
487
746
|
NSWritingDirection resolvedLayoutDirection = _resolvedLayoutDirection;
|
|
488
747
|
|
|
489
748
|
__block NSArray<ENRMRenderedSegment *> *renderedSegments = nil;
|
|
490
749
|
__block NSString *renderableMarkdown = nil;
|
|
750
|
+
__block BOOL endsInsideOpenCodeFence = NO;
|
|
491
751
|
|
|
492
752
|
[_renderCoordinator
|
|
493
753
|
scheduleRender:^BOOL {
|
|
494
|
-
renderableMarkdown = streamingAnimation
|
|
495
|
-
|
|
754
|
+
renderableMarkdown = streamingAnimation
|
|
755
|
+
? ENRMRenderableMarkdownForStreaming(markdownString, tableStreamingMode,
|
|
756
|
+
codeBlockStreamingMode, &endsInsideOpenCodeFence)
|
|
757
|
+
: markdownString;
|
|
496
758
|
|
|
497
759
|
if (renderableMarkdown.length == 0) {
|
|
498
760
|
renderedSegments = @[];
|
|
@@ -515,7 +777,9 @@ static char kENRMSegmentFadeAnimatorKey;
|
|
|
515
777
|
}
|
|
516
778
|
apply:^{
|
|
517
779
|
self->_renderedStyleFingerprint = self->_pendingStyleFingerprint;
|
|
518
|
-
[self applyRenderedSegments:renderedSegments
|
|
780
|
+
[self applyRenderedSegments:renderedSegments
|
|
781
|
+
renderedMarkdown:renderableMarkdown
|
|
782
|
+
endsInsideOpenCodeFence:endsInsideOpenCodeFence];
|
|
519
783
|
}];
|
|
520
784
|
}
|
|
521
785
|
|
|
@@ -552,8 +816,11 @@ static char kENRMSegmentFadeAnimatorKey;
|
|
|
552
816
|
|
|
553
817
|
_renderCoordinator.blockAsyncRender = YES;
|
|
554
818
|
_cachedMarkdown = [markdownString copy];
|
|
819
|
+
BOOL endsInsideOpenCodeFence = NO;
|
|
555
820
|
NSString *renderableMarkdown =
|
|
556
|
-
_streamingAnimation ? ENRMRenderableMarkdownForStreaming(markdownString, _tableStreamingMode
|
|
821
|
+
_streamingAnimation ? ENRMRenderableMarkdownForStreaming(markdownString, _tableStreamingMode,
|
|
822
|
+
_codeBlockStreamingMode, &endsInsideOpenCodeFence)
|
|
823
|
+
: markdownString;
|
|
557
824
|
_renderedMarkdown = [renderableMarkdown copy];
|
|
558
825
|
_renderedStyleFingerprint = _pendingStyleFingerprint;
|
|
559
826
|
|
|
@@ -566,6 +833,8 @@ static char kENRMSegmentFadeAnimatorKey;
|
|
|
566
833
|
return;
|
|
567
834
|
}
|
|
568
835
|
|
|
836
|
+
[self updatePendingCodeBlockSegment:endsInsideOpenCodeFence segments:renderedSegments];
|
|
837
|
+
|
|
569
838
|
for (ENRMRenderedSegment *segment in renderedSegments) {
|
|
570
839
|
RCTUIView *view = [_segmentViewRegistry createViewForSegment:segment];
|
|
571
840
|
[_segmentViews addObject:view];
|
|
@@ -574,9 +843,24 @@ static char kENRMSegmentFadeAnimatorKey;
|
|
|
574
843
|
}
|
|
575
844
|
}
|
|
576
845
|
|
|
577
|
-
- (void)
|
|
846
|
+
- (void)updatePendingCodeBlockSegment:(BOOL)endsInsideOpenCodeFence segments:(NSArray<ENRMRenderedSegment *> *)segments
|
|
847
|
+
{
|
|
848
|
+
_pendingCodeBlockSegment = nil;
|
|
849
|
+
if (!_streamingAnimation || !endsInsideOpenCodeFence) {
|
|
850
|
+
return;
|
|
851
|
+
}
|
|
852
|
+
ENRMRenderedSegment *last = segments.lastObject;
|
|
853
|
+
if (last.kind == ENRMSegmentKindCodeBlock) {
|
|
854
|
+
_pendingCodeBlockSegment = last.codeBlockSegment;
|
|
855
|
+
}
|
|
856
|
+
}
|
|
857
|
+
|
|
858
|
+
- (void)applyRenderedSegments:(NSArray *)renderedSegments
|
|
859
|
+
renderedMarkdown:(NSString *)renderedMarkdown
|
|
860
|
+
endsInsideOpenCodeFence:(BOOL)endsInsideOpenCodeFence
|
|
578
861
|
{
|
|
579
862
|
_renderedMarkdown = [renderedMarkdown copy];
|
|
863
|
+
[self updatePendingCodeBlockSegment:endsInsideOpenCodeFence segments:renderedSegments];
|
|
580
864
|
BOOL segmentTopologyChanged = _streamingAnimation && [self renderedSegmentsChangeTopology:renderedSegments];
|
|
581
865
|
|
|
582
866
|
ENRMSegmentReconciliationResult *result = [ENRMSegmentReconciler reconcileCurrentViews:_segmentViews
|
|
@@ -600,6 +884,15 @@ static char kENRMSegmentFadeAnimatorKey;
|
|
|
600
884
|
_segmentViews = result.views;
|
|
601
885
|
_segmentSignatures = result.signatures;
|
|
602
886
|
|
|
887
|
+
// A just-closed block has unchanged content, so the reconciler reuses it
|
|
888
|
+
// without an update; sync pending here to trigger its deferred highlight.
|
|
889
|
+
[_segmentViews enumerateObjectsUsingBlock:^(RCTUIView *segment, NSUInteger i, BOOL *stop) {
|
|
890
|
+
if ([segment isKindOfClass:[ENRMCodeBlockContainerView class]]) {
|
|
891
|
+
((ENRMCodeBlockContainerView *)segment).pending =
|
|
892
|
+
self->_pendingCodeBlockSegment != nil && i == self->_segmentViews.count - 1;
|
|
893
|
+
}
|
|
894
|
+
}];
|
|
895
|
+
|
|
603
896
|
if (self.bounds.size.width > 0) {
|
|
604
897
|
[self setNeedsLayout];
|
|
605
898
|
|
|
@@ -640,6 +933,7 @@ static char kENRMSegmentFadeAnimatorKey;
|
|
|
640
933
|
|
|
641
934
|
#if !TARGET_OS_OSX
|
|
642
935
|
view.textView.delegate = self;
|
|
936
|
+
[_selectionGestures trackTextView:view.textView];
|
|
643
937
|
#else
|
|
644
938
|
__weak EnrichedMarkdown *weakSelf = self;
|
|
645
939
|
[view setContextMenuProvider:^NSMenu *_Nullable(NSMenu *baseMenu, NSTextView *textView) {
|
|
@@ -647,6 +941,9 @@ static char kENRMSegmentFadeAnimatorKey;
|
|
|
647
941
|
if (!strongSelf) {
|
|
648
942
|
return baseMenu;
|
|
649
943
|
}
|
|
944
|
+
if (strongSelf->_contextMenuHidden) {
|
|
945
|
+
return nil;
|
|
946
|
+
}
|
|
650
947
|
NSString *segmentMarkdown = extractMarkdownFromAttributedString(textView.textStorage, textView.selectedRange);
|
|
651
948
|
NSArray<NSMenuItem *> *customItems = ENRMBuildContextMenuItems(
|
|
652
949
|
strongSelf->_contextMenuItemTexts, strongSelf->_contextMenuItemIcons, textView,
|
|
@@ -676,6 +973,10 @@ static char kENRMSegmentFadeAnimatorKey;
|
|
|
676
973
|
tableView.accessibilityLabels = _accessibilityLabels;
|
|
677
974
|
tableView.copyLabel = _selectionMenuLabels.copyLabel;
|
|
678
975
|
tableView.copyAsMarkdownLabel = _selectionMenuLabels.copyAsMarkdownLabel;
|
|
976
|
+
tableView.contextMenuHidden = _contextMenuHidden;
|
|
977
|
+
tableView.menuOptions = [self blockMenuOptions];
|
|
978
|
+
tableView.onCopyRequest = [self blockCopyRequestForSource:@"table"];
|
|
979
|
+
tableView.onMenuSuppressed = [self blockMenuSuppressedForSource:@"table" view:tableView];
|
|
679
980
|
|
|
680
981
|
__weak EnrichedMarkdown *weakSelf = self;
|
|
681
982
|
|
|
@@ -715,11 +1016,37 @@ static char kENRMSegmentFadeAnimatorKey;
|
|
|
715
1016
|
mathView.accessibilityLabels = _accessibilityLabels;
|
|
716
1017
|
mathView.copyLabel = _selectionMenuLabels.copyLabel;
|
|
717
1018
|
mathView.copyAsMarkdownLabel = _selectionMenuLabels.copyAsMarkdownLabel;
|
|
1019
|
+
mathView.contextMenuHidden = _contextMenuHidden;
|
|
1020
|
+
mathView.menuOptions = [self blockMenuOptions];
|
|
1021
|
+
mathView.onCopyRequest = [self blockCopyRequestForSource:@"math"];
|
|
1022
|
+
mathView.onMenuSuppressed = [self blockMenuSuppressedForSource:@"math" view:mathView];
|
|
718
1023
|
[mathView applyLatex:mathSegment.latex];
|
|
719
1024
|
return mathView;
|
|
720
1025
|
}
|
|
721
1026
|
#endif
|
|
722
1027
|
|
|
1028
|
+
- (ENRMCodeBlockContainerView *)createCodeBlockViewForSegment:(ENRMCodeBlockSegment *)codeBlockSegment
|
|
1029
|
+
{
|
|
1030
|
+
ENRMCodeBlockContainerView *codeBlockView = [[ENRMCodeBlockContainerView alloc] initWithConfig:_config];
|
|
1031
|
+
codeBlockView.copyLabel = _selectionMenuLabels.copyLabel;
|
|
1032
|
+
codeBlockView.copyAsMarkdownLabel = _selectionMenuLabels.copyAsMarkdownLabel;
|
|
1033
|
+
codeBlockView.contextMenuHidden = _contextMenuHidden;
|
|
1034
|
+
codeBlockView.menuOptions = [self blockMenuOptions];
|
|
1035
|
+
codeBlockView.onCopyRequest = [self blockCopyRequestForSource:@"code"];
|
|
1036
|
+
codeBlockView.onMenuSuppressed = [self blockMenuSuppressedForSource:@"code" view:codeBlockView];
|
|
1037
|
+
|
|
1038
|
+
__weak EnrichedMarkdown *weakSelf = self;
|
|
1039
|
+
codeBlockView.onCopyPress = ^(NSString *code, NSString *language) {
|
|
1040
|
+
EnrichedMarkdown *strongSelf = weakSelf;
|
|
1041
|
+
if (strongSelf)
|
|
1042
|
+
[strongSelf emitCopyPress:code language:language];
|
|
1043
|
+
};
|
|
1044
|
+
|
|
1045
|
+
codeBlockView.pending = codeBlockSegment == _pendingCodeBlockSegment;
|
|
1046
|
+
[codeBlockView applyCodeBlockNode:codeBlockSegment.codeBlockNode];
|
|
1047
|
+
return codeBlockView;
|
|
1048
|
+
}
|
|
1049
|
+
|
|
723
1050
|
- (void)animateBlockViewIfNeeded:(RCTUIView *)view
|
|
724
1051
|
{
|
|
725
1052
|
if (!_streamingAnimation)
|
|
@@ -759,6 +1086,9 @@ static char kENRMSegmentFadeAnimatorKey;
|
|
|
759
1086
|
{
|
|
760
1087
|
[super layoutSubviews];
|
|
761
1088
|
[self computeSegmentLayoutForWidth:self.bounds.size.width applyFrames:YES];
|
|
1089
|
+
[self emitLinkLayoutIfNeeded];
|
|
1090
|
+
// Segments may have moved or been replaced; re-read the selection (deduplicated).
|
|
1091
|
+
[_selectionReporter schedule];
|
|
762
1092
|
}
|
|
763
1093
|
|
|
764
1094
|
- (void)updateProps:(Props::Shared const &)props oldProps:(Props::Shared const &)oldProps
|
|
@@ -784,8 +1114,24 @@ static char kENRMSegmentFadeAnimatorKey;
|
|
|
784
1114
|
}
|
|
785
1115
|
}
|
|
786
1116
|
|
|
1117
|
+
if (ENRMImageRequestHeadersChanged(oldViewProps.imageRequestHeaders, newViewProps.imageRequestHeaders)) {
|
|
1118
|
+
[_config setImageRequestHeaders:ENRMImageRequestHeadersFromProps(newViewProps.imageRequestHeaders)];
|
|
1119
|
+
_dirtyFlags |= ENRMDirtyRender;
|
|
1120
|
+
if (!markdownChanged) {
|
|
1121
|
+
_dirtyFlags |= ENRMDirtyRecreateSegments;
|
|
1122
|
+
}
|
|
1123
|
+
}
|
|
1124
|
+
|
|
787
1125
|
_selectable = newViewProps.selectable;
|
|
788
1126
|
|
|
1127
|
+
if (newViewProps.emitLinkLayout != _emitLinkLayout) {
|
|
1128
|
+
_emitLinkLayout = newViewProps.emitLinkLayout;
|
|
1129
|
+
_lastLinkLayout = nil;
|
|
1130
|
+
[self setNeedsLayout];
|
|
1131
|
+
}
|
|
1132
|
+
|
|
1133
|
+
_selectionReporter.enabled = newViewProps.emitSelectionChange;
|
|
1134
|
+
|
|
789
1135
|
for (RCTUIView *segment in _segmentViews) {
|
|
790
1136
|
if ([segment isKindOfClass:[EnrichedMarkdownInternalText class]]) {
|
|
791
1137
|
EnrichedMarkdownInternalText *textSegment = (EnrichedMarkdownInternalText *)segment;
|
|
@@ -816,28 +1162,20 @@ static char kENRMSegmentFadeAnimatorKey;
|
|
|
816
1162
|
_dirtyFlags |= ENRMDirtyRecreateSegments | ENRMDirtyForceHeight | ENRMDirtyRender;
|
|
817
1163
|
}
|
|
818
1164
|
|
|
819
|
-
if (newViewProps.md4cFlags.underline != oldViewProps.md4cFlags.underline
|
|
820
|
-
|
|
821
|
-
|
|
822
|
-
|
|
823
|
-
|
|
824
|
-
|
|
825
|
-
|
|
826
|
-
}
|
|
827
|
-
if (newViewProps.md4cFlags.subscript != oldViewProps.md4cFlags.subscript) {
|
|
828
|
-
_md4cFlags.subscript = newViewProps.md4cFlags.subscript;
|
|
829
|
-
_dirtyFlags |= ENRMDirtyForceHeight | ENRMDirtyRender;
|
|
830
|
-
}
|
|
831
|
-
if (newViewProps.md4cFlags.latexMath != oldViewProps.md4cFlags.latexMath) {
|
|
832
|
-
_md4cFlags.latexMath = newViewProps.md4cFlags.latexMath;
|
|
833
|
-
_dirtyFlags |= ENRMDirtyForceHeight | ENRMDirtyRender;
|
|
834
|
-
}
|
|
835
|
-
if (newViewProps.md4cFlags.highlight != oldViewProps.md4cFlags.highlight) {
|
|
836
|
-
_md4cFlags.highlight = newViewProps.md4cFlags.highlight;
|
|
1165
|
+
if (newViewProps.md4cFlags.underline != oldViewProps.md4cFlags.underline ||
|
|
1166
|
+
newViewProps.md4cFlags.superscript != oldViewProps.md4cFlags.superscript ||
|
|
1167
|
+
newViewProps.md4cFlags.subscript != oldViewProps.md4cFlags.subscript ||
|
|
1168
|
+
newViewProps.md4cFlags.latexMath != oldViewProps.md4cFlags.latexMath ||
|
|
1169
|
+
newViewProps.md4cFlags.highlight != oldViewProps.md4cFlags.highlight ||
|
|
1170
|
+
newViewProps.md4cFlags.hardSoftBreaks != oldViewProps.md4cFlags.hardSoftBreaks) {
|
|
1171
|
+
_md4cFlags = [EnrichedMarkdown flagsFromProps:newViewProps.md4cFlags];
|
|
837
1172
|
_dirtyFlags |= ENRMDirtyForceHeight | ENRMDirtyRender;
|
|
838
1173
|
}
|
|
839
1174
|
|
|
840
1175
|
_enableLinkPreview = newViewProps.enableLinkPreview;
|
|
1176
|
+
_linkLongPressSelects = newViewProps.linkLongPressSelects;
|
|
1177
|
+
_enableTaskListItemToggle = newViewProps.enableTaskListItemToggle;
|
|
1178
|
+
_contextMenuHidden = newViewProps.contextMenuHidden;
|
|
841
1179
|
|
|
842
1180
|
if (newViewProps.streamingAnimation != oldViewProps.streamingAnimation) {
|
|
843
1181
|
_streamingAnimation = newViewProps.streamingAnimation;
|
|
@@ -862,15 +1200,21 @@ static char kENRMSegmentFadeAnimatorKey;
|
|
|
862
1200
|
_dirtyFlags |= ENRMDirtyForceHeight | ENRMDirtyRender;
|
|
863
1201
|
}
|
|
864
1202
|
|
|
1203
|
+
if (newViewProps.streamingConfig.codeBlockMode != oldViewProps.streamingConfig.codeBlockMode) {
|
|
1204
|
+
NSString *codeBlockModeStr =
|
|
1205
|
+
[[NSString alloc] initWithUTF8String:newViewProps.streamingConfig.codeBlockMode.c_str()];
|
|
1206
|
+
_codeBlockStreamingMode = [codeBlockModeStr isEqualToString:@"hidden"] ? ENRMCodeBlockStreamingModeHidden
|
|
1207
|
+
: ENRMCodeBlockStreamingModeProgressive;
|
|
1208
|
+
_dirtyFlags |= ENRMDirtyForceHeight | ENRMDirtyRender;
|
|
1209
|
+
}
|
|
1210
|
+
|
|
865
1211
|
if (ENRMContextMenuItemsChanged(oldViewProps.contextMenuItems, newViewProps.contextMenuItems)) {
|
|
866
1212
|
_contextMenuItemTexts = ENRMContextMenuTextsFromItems(newViewProps.contextMenuItems);
|
|
867
1213
|
_contextMenuItemIcons = ENRMContextMenuIconsFromItems(newViewProps.contextMenuItems);
|
|
868
1214
|
}
|
|
869
1215
|
|
|
870
1216
|
_selectionMenuLabels = ENRMParseSelectionMenuLabels(newViewProps.selectionMenuConfig);
|
|
871
|
-
_selectionMenuConfig =
|
|
872
|
-
ENRMBuildSelectionMenuConfig(_selectionMenuLabels, newViewProps.selectionMenuConfig.copyAsMarkdown,
|
|
873
|
-
newViewProps.selectionMenuConfig.copyImageUrl);
|
|
1217
|
+
_selectionMenuConfig = ENRMBuildSelectionMenuConfig(_selectionMenuLabels, newViewProps.selectionMenuConfig);
|
|
874
1218
|
[self pushSelectionMenuLabelsToSegments];
|
|
875
1219
|
|
|
876
1220
|
if (ENRMAccessibilityLabelsChanged(oldViewProps.accessibilityLabels, newViewProps.accessibilityLabels)) {
|
|
@@ -964,7 +1308,8 @@ static char kENRMSegmentFadeAnimatorKey;
|
|
|
964
1308
|
|
|
965
1309
|
- (void)prepareForRecycle
|
|
966
1310
|
{
|
|
967
|
-
|
|
1311
|
+
const auto resetProps = std::make_shared<const EnrichedMarkdownProps>();
|
|
1312
|
+
_props = resetProps;
|
|
968
1313
|
[_renderCoordinator invalidate];
|
|
969
1314
|
|
|
970
1315
|
for (RCTUIView *segment in _segmentViews) {
|
|
@@ -982,8 +1327,39 @@ static char kENRMSegmentFadeAnimatorKey;
|
|
|
982
1327
|
|
|
983
1328
|
_cachedMarkdown = nil;
|
|
984
1329
|
_renderedMarkdown = nil;
|
|
1330
|
+
_config = nil;
|
|
1331
|
+
_emitLinkLayout = NO;
|
|
1332
|
+
_lastLinkLayout = nil;
|
|
1333
|
+
_selectionReporter.enabled = NO;
|
|
1334
|
+
#if !TARGET_OS_OSX
|
|
1335
|
+
[_selectionGestures reset];
|
|
1336
|
+
#endif
|
|
1337
|
+
_selectionOwner = nil;
|
|
1338
|
+
[self clearActiveBlock];
|
|
1339
|
+
_md4cFlags = [EnrichedMarkdown flagsFromProps:resetProps->md4cFlags];
|
|
1340
|
+
_maxFontSizeMultiplier = 0;
|
|
1341
|
+
_allowTrailingMargin = NO;
|
|
1342
|
+
_streamingAnimation = NO;
|
|
1343
|
+
_tableStreamingMode = ENRMTableStreamingModeProgressive;
|
|
1344
|
+
_codeBlockStreamingMode = ENRMCodeBlockStreamingModeProgressive;
|
|
1345
|
+
_pendingCodeBlockSegment = nil;
|
|
1346
|
+
_lineBreakStrategy = NSLineBreakStrategyNone;
|
|
1347
|
+
_writingDirectionMode = ENRMWritingDirectionModeFirstStrong;
|
|
1348
|
+
_renderedStyleFingerprint = 0;
|
|
1349
|
+
_pendingStyleFingerprint = 0;
|
|
1350
|
+
_contextMenuItemTexts = nil;
|
|
1351
|
+
_contextMenuItemIcons = nil;
|
|
1352
|
+
_fontScaleObserver.allowFontScaling = resetProps->allowFontScaling;
|
|
1353
|
+
_accessibilityLabels = nil;
|
|
1354
|
+
_spoilerOverlay =
|
|
1355
|
+
ENRMSpoilerOverlayFromString([[NSString alloc] initWithUTF8String:resetProps->spoilerOverlay.c_str()]);
|
|
1356
|
+
_dirtyFlags = ENRMDirtyNone;
|
|
985
1357
|
|
|
986
|
-
|
|
1358
|
+
// Ported from the fork's resetPropDerivedState: upstream's prepareForRecycle covers every
|
|
1359
|
+
// other prop-derived ivar but leaves these two, so a recycled view keeps the previous
|
|
1360
|
+
// consumer's height-update counter and a dangling shadow-node state handle.
|
|
1361
|
+
_heightUpdateCounter = 0;
|
|
1362
|
+
_state = nullptr;
|
|
987
1363
|
|
|
988
1364
|
[super prepareForRecycle];
|
|
989
1365
|
}
|
|
@@ -1070,6 +1446,40 @@ Class<RCTComponentViewProtocol> EnrichedMarkdownCls(void)
|
|
|
1070
1446
|
emitter->onLinkPress({.url = std::string(url.UTF8String)});
|
|
1071
1447
|
}
|
|
1072
1448
|
|
|
1449
|
+
/// Reports link rects of every text segment (offset by the segment origin) to
|
|
1450
|
+
/// JS for `renderLinkDecoration`. Tables are skipped: their cells scroll
|
|
1451
|
+
/// horizontally, so rects would go stale. Runs after each segment layout pass;
|
|
1452
|
+
/// deduplicated so an unchanged layout sends nothing.
|
|
1453
|
+
- (void)emitLinkLayoutIfNeeded
|
|
1454
|
+
{
|
|
1455
|
+
if (!_emitLinkLayout || self.bounds.size.width <= 0)
|
|
1456
|
+
return;
|
|
1457
|
+
|
|
1458
|
+
auto emitter = std::static_pointer_cast<EnrichedMarkdownEventEmitter const>(_eventEmitter);
|
|
1459
|
+
if (!emitter)
|
|
1460
|
+
return;
|
|
1461
|
+
|
|
1462
|
+
NSMutableArray<NSDictionary *> *fragments = [NSMutableArray array];
|
|
1463
|
+
NSInteger linkCount = 0;
|
|
1464
|
+
for (RCTUIView *segment in _segmentViews) {
|
|
1465
|
+
if ([segment isKindOfClass:[TableContainerView class]]) {
|
|
1466
|
+
linkCount += ((TableContainerView *)segment).linkCount;
|
|
1467
|
+
continue;
|
|
1468
|
+
}
|
|
1469
|
+
if (![segment isKindOfClass:[EnrichedMarkdownInternalText class]])
|
|
1470
|
+
continue;
|
|
1471
|
+
NSInteger segmentLinks = 0;
|
|
1472
|
+
[fragments addObjectsFromArray:ENRMCollectLinkLayoutFragments(((EnrichedMarkdownInternalText *)segment).textView,
|
|
1473
|
+
segment.frame.origin, linkCount, &segmentLinks)];
|
|
1474
|
+
linkCount += segmentLinks;
|
|
1475
|
+
}
|
|
1476
|
+
|
|
1477
|
+
if (_lastLinkLayout != nil && [fragments isEqualToArray:_lastLinkLayout])
|
|
1478
|
+
return;
|
|
1479
|
+
_lastLinkLayout = [fragments copy];
|
|
1480
|
+
emitter->onLinkLayout(ENRMLinkLayoutEventFromFragments<EnrichedMarkdownEventEmitter::OnLinkLayout>(fragments));
|
|
1481
|
+
}
|
|
1482
|
+
|
|
1073
1483
|
- (void)emitLinkLongPress:(NSString *)url
|
|
1074
1484
|
{
|
|
1075
1485
|
auto emitter = std::static_pointer_cast<EnrichedMarkdownEventEmitter const>(_eventEmitter);
|
|
@@ -1084,6 +1494,26 @@ Class<RCTComponentViewProtocol> EnrichedMarkdownCls(void)
|
|
|
1084
1494
|
emitter->onTaskListItemPress({.index = (int)index, .checked = checked, .text = std::string(text.UTF8String ?: "")});
|
|
1085
1495
|
}
|
|
1086
1496
|
|
|
1497
|
+
- (void)emitCopyPress:(NSString *)code language:(NSString *)language
|
|
1498
|
+
{
|
|
1499
|
+
auto emitter = std::static_pointer_cast<EnrichedMarkdownEventEmitter const>(_eventEmitter);
|
|
1500
|
+
if (emitter)
|
|
1501
|
+
emitter->onCopyPress(
|
|
1502
|
+
{.code = std::string(code.UTF8String ?: ""), .language = std::string(language.UTF8String ?: "")});
|
|
1503
|
+
}
|
|
1504
|
+
|
|
1505
|
+
- (void)emitCopyRequest:(NSString *)source markdown:(NSString *)markdown text:(NSString *)text whole:(BOOL)whole
|
|
1506
|
+
{
|
|
1507
|
+
auto emitter = std::static_pointer_cast<EnrichedMarkdownEventEmitter const>(_eventEmitter);
|
|
1508
|
+
if (emitter)
|
|
1509
|
+
emitter->onCopyRequest({
|
|
1510
|
+
.source = std::string(source.UTF8String),
|
|
1511
|
+
.markdown = std::string(markdown.UTF8String ?: ""),
|
|
1512
|
+
.text = std::string(text.UTF8String ?: ""),
|
|
1513
|
+
.whole = (bool)whole,
|
|
1514
|
+
});
|
|
1515
|
+
}
|
|
1516
|
+
|
|
1087
1517
|
- (void)emitContextMenuItemPress:(NSString *)itemText
|
|
1088
1518
|
selectedText:(NSString *)selectedText
|
|
1089
1519
|
selectionStart:(NSUInteger)selectionStart
|
|
@@ -1103,7 +1533,8 @@ Class<RCTComponentViewProtocol> EnrichedMarkdownCls(void)
|
|
|
1103
1533
|
{
|
|
1104
1534
|
ENRMPlatformTextView *textView = (ENRMPlatformTextView *)recognizer.view;
|
|
1105
1535
|
|
|
1106
|
-
if (
|
|
1536
|
+
if (_enableTaskListItemToggle &&
|
|
1537
|
+
handleTaskListTapWithSharedLogic(
|
|
1107
1538
|
textView, recognizer, &self->_cachedMarkdown, self->_config,
|
|
1108
1539
|
^(NSInteger index, BOOL checked, NSString *itemText) {
|
|
1109
1540
|
[self emitTaskListItemPress:index checked:checked text:itemText];
|
|
@@ -1126,12 +1557,37 @@ Class<RCTComponentViewProtocol> EnrichedMarkdownCls(void)
|
|
|
1126
1557
|
ENRMHandleTapOnTextView(textView, recognizer, ^(NSString *url) { [self emitLinkPress:url]; });
|
|
1127
1558
|
}
|
|
1128
1559
|
|
|
1560
|
+
#if !TARGET_OS_OSX
|
|
1561
|
+
- (void)textViewDidChangeSelection:(UITextView *)textView
|
|
1562
|
+
{
|
|
1563
|
+
[_selectionGestures trackTextView:textView];
|
|
1564
|
+
ENRMDismissSelectionEditMenuIfMoved(textView);
|
|
1565
|
+
if (textView.selectedRange.length > 0) {
|
|
1566
|
+
// Take ownership first so the previous owner's own "cleared" callback is ignored.
|
|
1567
|
+
ENRMPlatformTextView *previous = _selectionOwner;
|
|
1568
|
+
_selectionOwner = textView;
|
|
1569
|
+
[self clearActiveBlock];
|
|
1570
|
+
if (previous && previous != textView)
|
|
1571
|
+
previous.selectedRange = NSMakeRange(0, 0);
|
|
1572
|
+
[_selectionReporter schedule];
|
|
1573
|
+
} else if (textView == _selectionOwner) {
|
|
1574
|
+
[_selectionReporter selectionChanged:NO];
|
|
1575
|
+
}
|
|
1576
|
+
}
|
|
1577
|
+
#endif
|
|
1578
|
+
|
|
1129
1579
|
// TODO: Remove API_AVAILABLE(ios(16.0)) guard when the minimum iOS deployment target in RN is bumped to 16.
|
|
1130
1580
|
#if !TARGET_OS_OSX
|
|
1131
1581
|
- (UIMenu *)textView:(UITextView *)textView
|
|
1132
1582
|
editMenuForTextInRange:(NSRange)range
|
|
1133
1583
|
suggestedActions:(NSArray<UIMenuElement *> *)suggestedActions API_AVAILABLE(ios(16.0))
|
|
1134
1584
|
{
|
|
1585
|
+
// An empty menu presents nothing; nil would make UIKit show its default menu
|
|
1586
|
+
// (the selection and handles stay either way).
|
|
1587
|
+
if (_contextMenuHidden) {
|
|
1588
|
+
return [UIMenu menuWithChildren:@[]];
|
|
1589
|
+
}
|
|
1590
|
+
|
|
1135
1591
|
__weak EnrichedMarkdown *weakSelf = self;
|
|
1136
1592
|
ENRMContextMenuPressHandler handler =
|
|
1137
1593
|
^(NSString *itemText, NSString *selectedText, NSUInteger selectionStart, NSUInteger selectionEnd) {
|
|
@@ -1146,8 +1602,47 @@ Class<RCTComponentViewProtocol> EnrichedMarkdownCls(void)
|
|
|
1146
1602
|
ENRMBuildContextMenuActions(_contextMenuItemTexts, _contextMenuItemIcons, textView, range, handler);
|
|
1147
1603
|
|
|
1148
1604
|
NSString *segmentMarkdown = extractMarkdownFromAttributedString(textView.attributedText, range);
|
|
1605
|
+
|
|
1606
|
+
// Segments only see their own text, so a selection is the whole component
|
|
1607
|
+
// only when it spans the sole segment; the markdown is then the original.
|
|
1608
|
+
ENRMCopyRequestHandler onCopyRequest = ^(NSString *markdown, NSString *text, BOOL fullSelection) {
|
|
1609
|
+
EnrichedMarkdown *strongSelf = weakSelf;
|
|
1610
|
+
if (!strongSelf)
|
|
1611
|
+
return;
|
|
1612
|
+
BOOL whole = fullSelection && strongSelf->_segmentViews.count == 1 && strongSelf->_cachedMarkdown.length > 0;
|
|
1613
|
+
[strongSelf emitCopyRequest:@"selection"
|
|
1614
|
+
markdown:whole ? strongSelf->_cachedMarkdown : markdown
|
|
1615
|
+
text:text
|
|
1616
|
+
whole:whole];
|
|
1617
|
+
};
|
|
1618
|
+
|
|
1149
1619
|
return buildEditMenuForSelection(textView.attributedText, range, segmentMarkdown, _config, suggestedActions,
|
|
1150
|
-
customActions, _selectionMenuConfig);
|
|
1620
|
+
customActions, _selectionMenuConfig, onCopyRequest);
|
|
1621
|
+
}
|
|
1622
|
+
|
|
1623
|
+
// Attachments other than images (inline math) are text, not items: without
|
|
1624
|
+
// this a long press on one in an unfocused text view starts UIKit's text item
|
|
1625
|
+
// interaction, which presents nothing and leaves the view unable to select.
|
|
1626
|
+
- (BOOL)textView:(UITextView *)textView
|
|
1627
|
+
shouldInteractWithTextAttachment:(NSTextAttachment *)textAttachment
|
|
1628
|
+
inRange:(NSRange)characterRange
|
|
1629
|
+
interaction:(UITextItemInteraction)interaction
|
|
1630
|
+
{
|
|
1631
|
+
if ([textAttachment isKindOfClass:[ENRMImageAttachment class]]) {
|
|
1632
|
+
return YES;
|
|
1633
|
+
}
|
|
1634
|
+
// A long press selects the attachment like a word, as it does once the view is focused.
|
|
1635
|
+
if (interaction == UITextItemInteractionPresentActions) {
|
|
1636
|
+
__weak UITextView *weakTextView = textView;
|
|
1637
|
+
dispatch_async(dispatch_get_main_queue(), ^{
|
|
1638
|
+
UITextView *strongTextView = weakTextView;
|
|
1639
|
+
if (!strongTextView || NSMaxRange(characterRange) > strongTextView.attributedText.length) {
|
|
1640
|
+
return;
|
|
1641
|
+
}
|
|
1642
|
+
ENRMSelectRangeAndPresentEditMenu(strongTextView, characterRange);
|
|
1643
|
+
});
|
|
1644
|
+
}
|
|
1645
|
+
return NO;
|
|
1151
1646
|
}
|
|
1152
1647
|
|
|
1153
1648
|
- (BOOL)textView:(UITextView *)textView
|
|
@@ -1161,6 +1656,18 @@ Class<RCTComponentViewProtocol> EnrichedMarkdownCls(void)
|
|
|
1161
1656
|
|
|
1162
1657
|
NSString *urlString = linkURLAtRange(textView, characterRange);
|
|
1163
1658
|
|
|
1659
|
+
if (urlString && _linkLongPressSelects) {
|
|
1660
|
+
__weak UITextView *weakTextView = textView;
|
|
1661
|
+
dispatch_async(dispatch_get_main_queue(), ^{
|
|
1662
|
+
UITextView *strongTextView = weakTextView;
|
|
1663
|
+
if (!strongTextView || NSMaxRange(characterRange) > strongTextView.attributedText.length) {
|
|
1664
|
+
return;
|
|
1665
|
+
}
|
|
1666
|
+
ENRMSelectRangeAndPresentEditMenu(strongTextView, characterRange);
|
|
1667
|
+
});
|
|
1668
|
+
return NO;
|
|
1669
|
+
}
|
|
1670
|
+
|
|
1164
1671
|
if (!urlString || _enableLinkPreview) {
|
|
1165
1672
|
return YES;
|
|
1166
1673
|
}
|