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/android/src/main/java/com/swmansion/enriched/markdown/utils/text/view/SelectionActionMode.kt
CHANGED
|
@@ -12,6 +12,7 @@ import android.widget.TextView
|
|
|
12
12
|
import com.swmansion.enriched.markdown.EnrichedMarkdown
|
|
13
13
|
import com.swmansion.enriched.markdown.EnrichedMarkdownText
|
|
14
14
|
import com.swmansion.enriched.markdown.spans.ImageSpan
|
|
15
|
+
import com.swmansion.enriched.markdown.spans.LinkSpacers
|
|
15
16
|
import com.swmansion.enriched.markdown.styles.StyleConfig
|
|
16
17
|
import com.swmansion.enriched.markdown.utils.common.layout.isLayoutRTL
|
|
17
18
|
import com.swmansion.enriched.markdown.utils.text.conversion.HTMLGenerator
|
|
@@ -32,6 +33,14 @@ data class SelectionMenuConfig(
|
|
|
32
33
|
// Plural templates indexed by image count (0..100). Empty when no pluralLabels
|
|
33
34
|
// are set; counts > 100 use copyImageUrlsLabel (the "other" form).
|
|
34
35
|
val copyImageUrlPluralTemplates: List<String> = emptyList(),
|
|
36
|
+
val copyEnabled: Boolean = true,
|
|
37
|
+
// Copy writes Markdown (plain text) instead of plain + HTML / raw block content.
|
|
38
|
+
val copyFormatMarkdown: Boolean = false,
|
|
39
|
+
// Drop every system-provided item (Select all, Share, text assist, PROCESS_TEXT…).
|
|
40
|
+
val systemItemsNone: Boolean = false,
|
|
41
|
+
val codeBlockCopyButton: Boolean = true,
|
|
42
|
+
// Copy hands the selection to onCopyRequest instead of writing the clipboard.
|
|
43
|
+
val interceptCopy: Boolean = false,
|
|
35
44
|
)
|
|
36
45
|
|
|
37
46
|
/**
|
|
@@ -57,14 +66,24 @@ fun createSelectionActionModeCallback(
|
|
|
57
66
|
textView: TextView,
|
|
58
67
|
getCustomItemTexts: () -> List<String> = { emptyList() },
|
|
59
68
|
getSelectionMenuConfig: () -> SelectionMenuConfig = { SelectionMenuConfig() },
|
|
69
|
+
isContextMenuHidden: () -> Boolean = { false },
|
|
70
|
+
// Lets the owning view hold the live ActionMode so it can invalidate() the
|
|
71
|
+
// toolbar when a prop changes while the menu is already on screen.
|
|
72
|
+
onActionModeChanged: (mode: ActionMode?) -> Unit = {},
|
|
60
73
|
onCustomItemPress: (itemText: String, selectedText: String, selectionStart: Int, selectionEnd: Int) -> Unit =
|
|
61
74
|
{ _, _, _, _ -> },
|
|
75
|
+
// Receives the intercepted Copy when `interceptCopy` is set. `fullSelection`
|
|
76
|
+
// is whether the selection spans the whole text view.
|
|
77
|
+
onCopyRequest: (markdown: String, text: String, fullSelection: Boolean) -> Unit = { _, _, _ -> },
|
|
62
78
|
): ActionMode.Callback =
|
|
63
79
|
object : ActionMode.Callback {
|
|
64
80
|
override fun onCreateActionMode(
|
|
65
81
|
mode: ActionMode?,
|
|
66
82
|
menu: Menu?,
|
|
67
|
-
): Boolean
|
|
83
|
+
): Boolean {
|
|
84
|
+
onActionModeChanged(mode)
|
|
85
|
+
return true
|
|
86
|
+
}
|
|
68
87
|
|
|
69
88
|
override fun onPrepareActionMode(
|
|
70
89
|
mode: ActionMode?,
|
|
@@ -72,24 +91,39 @@ fun createSelectionActionModeCallback(
|
|
|
72
91
|
): Boolean {
|
|
73
92
|
if (menu == null) return false
|
|
74
93
|
|
|
94
|
+
// Keep the ActionMode alive (selection handles and highlighting stay
|
|
95
|
+
// usable, which is what TalkBack relies on) but ship an empty menu so
|
|
96
|
+
// the floating toolbar has nothing to show.
|
|
97
|
+
if (isContextMenuHidden()) {
|
|
98
|
+
menu.clear()
|
|
99
|
+
return true
|
|
100
|
+
}
|
|
101
|
+
|
|
75
102
|
menu.removeItem(MENU_ITEM_COPY_MARKDOWN)
|
|
76
103
|
menu.removeItem(MENU_ITEM_COPY_IMAGE_URL)
|
|
77
104
|
menu.removeGroup(MENU_ITEM_CUSTOM_GROUP)
|
|
78
105
|
|
|
79
106
|
val selectionMenuConfig = getSelectionMenuConfig()
|
|
107
|
+
val hasSelection = textView.selectionStart >= 0 && textView.selectionEnd > textView.selectionStart
|
|
80
108
|
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
109
|
+
if (selectionMenuConfig.systemItemsNone) {
|
|
110
|
+
// Editor re-adds Select all and the text-assist items before calling
|
|
111
|
+
// us on every prepare, so clear on each pass and put back only Copy.
|
|
112
|
+
// Its click is still intercepted in onActionItemClicked.
|
|
113
|
+
menu.clear()
|
|
114
|
+
if (selectionMenuConfig.copyEnabled && hasSelection) {
|
|
115
|
+
menu.add(Menu.NONE, android.R.id.copy, Menu.NONE, selectionMenuConfig.copyLabel)
|
|
116
|
+
}
|
|
117
|
+
} else if (!selectionMenuConfig.copyEnabled) {
|
|
118
|
+
menu.removeItem(android.R.id.copy)
|
|
119
|
+
} else if (selectionMenuConfig.copyLabel.isNotEmpty()) {
|
|
120
|
+
// The system Copy item is added by the platform; relabel it so it
|
|
121
|
+
// matches the rest of the localized menu (iOS rebuilds the menu so
|
|
122
|
+
// gets this for free; Android only intercepts the click).
|
|
85
123
|
menu.findItem(android.R.id.copy)?.title = selectionMenuConfig.copyLabel
|
|
86
124
|
}
|
|
87
125
|
|
|
88
|
-
if (
|
|
89
|
-
selectionMenuConfig.copyAsMarkdown &&
|
|
90
|
-
textView.selectionStart >= 0 &&
|
|
91
|
-
textView.selectionEnd > textView.selectionStart
|
|
92
|
-
) {
|
|
126
|
+
if (selectionMenuConfig.copyAsMarkdown && hasSelection) {
|
|
93
127
|
menu.add(
|
|
94
128
|
Menu.NONE,
|
|
95
129
|
MENU_ITEM_COPY_MARKDOWN,
|
|
@@ -98,7 +132,7 @@ fun createSelectionActionModeCallback(
|
|
|
98
132
|
)
|
|
99
133
|
}
|
|
100
134
|
|
|
101
|
-
if (
|
|
135
|
+
if (hasSelection) {
|
|
102
136
|
val customItems = getCustomItemTexts()
|
|
103
137
|
customItems.forEachIndexed { index, text ->
|
|
104
138
|
menu
|
|
@@ -129,7 +163,12 @@ fun createSelectionActionModeCallback(
|
|
|
129
163
|
|
|
130
164
|
when (itemId) {
|
|
131
165
|
android.R.id.copy -> {
|
|
132
|
-
|
|
166
|
+
val config = getSelectionMenuConfig()
|
|
167
|
+
if (config.interceptCopy) {
|
|
168
|
+
textView.requestCopy(onCopyRequest)
|
|
169
|
+
} else if (!config.copyFormatMarkdown || !textView.copyMarkdownToClipboard()) {
|
|
170
|
+
textView.copyWithHTML()
|
|
171
|
+
}
|
|
133
172
|
mode?.finish()
|
|
134
173
|
return true
|
|
135
174
|
}
|
|
@@ -161,7 +200,9 @@ fun createSelectionActionModeCallback(
|
|
|
161
200
|
return false
|
|
162
201
|
}
|
|
163
202
|
|
|
164
|
-
override fun onDestroyActionMode(mode: ActionMode?) {
|
|
203
|
+
override fun onDestroyActionMode(mode: ActionMode?) {
|
|
204
|
+
onActionModeChanged(null)
|
|
205
|
+
}
|
|
165
206
|
}
|
|
166
207
|
|
|
167
208
|
/** Copies selection as both plain text and HTML with inline styles. */
|
|
@@ -171,7 +212,8 @@ private fun TextView.copyWithHTML() {
|
|
|
171
212
|
if (start < 0 || end < 0 || start >= end) return
|
|
172
213
|
|
|
173
214
|
val spannable = text as? Spannable ?: return
|
|
174
|
-
|
|
215
|
+
// Link spacers only reserve layout space; keep them out of every copied flavor.
|
|
216
|
+
val selectedText = LinkSpacers.strip(spannable.subSequence(start, end))
|
|
175
217
|
val plainText = selectedText.toString()
|
|
176
218
|
|
|
177
219
|
val styleConfig =
|
|
@@ -197,10 +239,24 @@ private fun TextView.copyWithHTML() {
|
|
|
197
239
|
}
|
|
198
240
|
}
|
|
199
241
|
|
|
200
|
-
|
|
201
|
-
|
|
242
|
+
/** Hands the selection to [onCopyRequest] without touching the clipboard. */
|
|
243
|
+
private fun TextView.requestCopy(onCopyRequest: (markdown: String, text: String, fullSelection: Boolean) -> Unit) {
|
|
244
|
+
val start = selectionStart
|
|
245
|
+
val end = selectionEnd
|
|
246
|
+
if (start < 0 || end < 0 || start >= end) return
|
|
247
|
+
|
|
248
|
+
val selectedText = LinkSpacers.strip(text.subSequence(start, end)).toString()
|
|
249
|
+
val markdown = MarkdownExtractor.getMarkdownForSelection(this) ?: selectedText
|
|
250
|
+
// Same threshold MarkdownExtractor uses to return the original markdown.
|
|
251
|
+
onCopyRequest(markdown, selectedText, start == 0 && end >= text.length - 1)
|
|
252
|
+
}
|
|
253
|
+
|
|
254
|
+
/** Returns false when the selection has no Markdown to copy. */
|
|
255
|
+
private fun TextView.copyMarkdownToClipboard(): Boolean {
|
|
256
|
+
val markdown = MarkdownExtractor.getMarkdownForSelection(this) ?: return false
|
|
202
257
|
val clipboard = context.getSystemService(Context.CLIPBOARD_SERVICE) as ClipboardManager
|
|
203
258
|
clipboard.setPrimaryClip(ClipData.newPlainText("Markdown", markdown))
|
|
259
|
+
return true
|
|
204
260
|
}
|
|
205
261
|
|
|
206
262
|
/** Returns remote image URLs (http/https only) from the current selection. */
|
|
@@ -0,0 +1,232 @@
|
|
|
1
|
+
package com.swmansion.enriched.markdown.utils.text.view
|
|
2
|
+
|
|
3
|
+
import android.text.Layout
|
|
4
|
+
import android.text.Selection
|
|
5
|
+
import android.text.Spannable
|
|
6
|
+
import android.view.View
|
|
7
|
+
import android.widget.TextView
|
|
8
|
+
import com.facebook.react.uimanager.PixelUtil
|
|
9
|
+
import com.swmansion.enriched.markdown.spans.LinkSpacers
|
|
10
|
+
import com.swmansion.enriched.markdown.utils.text.conversion.MarkdownExtractor
|
|
11
|
+
import kotlin.math.max
|
|
12
|
+
import kotlin.math.min
|
|
13
|
+
|
|
14
|
+
/** A rect in dp, relative to the reporting view. */
|
|
15
|
+
data class SelectionRect(
|
|
16
|
+
val x: Float,
|
|
17
|
+
val y: Float,
|
|
18
|
+
val width: Float,
|
|
19
|
+
val height: Float,
|
|
20
|
+
) {
|
|
21
|
+
companion object {
|
|
22
|
+
val ZERO = SelectionRect(0f, 0f, 0f, 0f)
|
|
23
|
+
|
|
24
|
+
/** Converts a px rect (already in the reporting view's coordinates) to dp. */
|
|
25
|
+
fun fromPx(
|
|
26
|
+
left: Float,
|
|
27
|
+
top: Float,
|
|
28
|
+
right: Float,
|
|
29
|
+
bottom: Float,
|
|
30
|
+
) = SelectionRect(
|
|
31
|
+
PixelUtil.toDIPFromPixel(min(left, right)),
|
|
32
|
+
PixelUtil.toDIPFromPixel(min(top, bottom)),
|
|
33
|
+
PixelUtil.toDIPFromPixel(kotlin.math.abs(right - left)),
|
|
34
|
+
PixelUtil.toDIPFromPixel(kotlin.math.abs(bottom - top)),
|
|
35
|
+
)
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
/** Payload of `onSelectionChange`. Compared structurally for deduplication. */
|
|
40
|
+
data class SelectionSnapshot(
|
|
41
|
+
val active: Boolean,
|
|
42
|
+
val source: String,
|
|
43
|
+
val text: String,
|
|
44
|
+
val markdown: String,
|
|
45
|
+
val whole: Boolean,
|
|
46
|
+
val rect: SelectionRect,
|
|
47
|
+
val startRect: SelectionRect,
|
|
48
|
+
val endRect: SelectionRect,
|
|
49
|
+
// Not tracked on Android: the selection is reported continuously while a handle is dragged.
|
|
50
|
+
val adjusting: Boolean = false,
|
|
51
|
+
) {
|
|
52
|
+
companion object {
|
|
53
|
+
val INACTIVE =
|
|
54
|
+
SelectionSnapshot(false, "selection", "", "", false, SelectionRect.ZERO, SelectionRect.ZERO, SelectionRect.ZERO)
|
|
55
|
+
|
|
56
|
+
/** A long-pressed block: `whole`, and every rect is the block's frame. */
|
|
57
|
+
fun block(
|
|
58
|
+
source: String,
|
|
59
|
+
markdown: String,
|
|
60
|
+
text: String,
|
|
61
|
+
rect: SelectionRect,
|
|
62
|
+
) = SelectionSnapshot(true, source, text, markdown, true, rect, rect, rect)
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
/** A text view's current selection, before the owner applies its `whole` rule. */
|
|
67
|
+
data class TextSelection(
|
|
68
|
+
val text: String,
|
|
69
|
+
val markdown: String,
|
|
70
|
+
// Same threshold MarkdownExtractor uses to return the original markdown.
|
|
71
|
+
val fullSelection: Boolean,
|
|
72
|
+
val rect: SelectionRect,
|
|
73
|
+
val startRect: SelectionRect,
|
|
74
|
+
val endRect: SelectionRect,
|
|
75
|
+
)
|
|
76
|
+
|
|
77
|
+
/**
|
|
78
|
+
* Reads the selection of this text view with its rects offset by [offsetXPx]/[offsetYPx]
|
|
79
|
+
* (a segment's position inside its container). `rect` spans the full content width when the
|
|
80
|
+
* selection covers several lines; `startRect`/`endRect` cover the selected part of the first
|
|
81
|
+
* and last line. Returns null when nothing is selected.
|
|
82
|
+
*/
|
|
83
|
+
fun TextView.currentTextSelection(
|
|
84
|
+
offsetXPx: Int = 0,
|
|
85
|
+
offsetYPx: Int = 0,
|
|
86
|
+
): TextSelection? {
|
|
87
|
+
val start = selectionStart
|
|
88
|
+
val end = selectionEnd
|
|
89
|
+
if (start < 0 || end <= start) return null
|
|
90
|
+
val layout = layout ?: return null
|
|
91
|
+
val content = text ?: return null
|
|
92
|
+
|
|
93
|
+
val selectedText = LinkSpacers.strip(content.subSequence(start, end)).toString()
|
|
94
|
+
val markdown = MarkdownExtractor.getMarkdownForSelection(this) ?: selectedText
|
|
95
|
+
|
|
96
|
+
val originX = (offsetXPx + totalPaddingLeft - scrollX).toFloat()
|
|
97
|
+
val originY = (offsetYPx + totalPaddingTop - scrollY).toFloat()
|
|
98
|
+
|
|
99
|
+
val startLine = layout.getLineForOffset(start)
|
|
100
|
+
// An end at a line break belongs to the line it closes, not the next one.
|
|
101
|
+
val endLine = layout.getLineForOffset(max(start, end - 1))
|
|
102
|
+
val startX = layout.getPrimaryHorizontal(start)
|
|
103
|
+
val endX = lineEndHorizontal(layout, endLine, end)
|
|
104
|
+
|
|
105
|
+
fun lineRect(
|
|
106
|
+
line: Int,
|
|
107
|
+
left: Float,
|
|
108
|
+
right: Float,
|
|
109
|
+
) = SelectionRect.fromPx(
|
|
110
|
+
left + originX,
|
|
111
|
+
layout.getLineTop(line) + originY,
|
|
112
|
+
right + originX,
|
|
113
|
+
layout.getLineBottom(line) + originY,
|
|
114
|
+
)
|
|
115
|
+
|
|
116
|
+
val startRect: SelectionRect
|
|
117
|
+
val endRect: SelectionRect
|
|
118
|
+
val rect: SelectionRect
|
|
119
|
+
if (startLine == endLine) {
|
|
120
|
+
startRect = lineRect(startLine, startX, endX)
|
|
121
|
+
endRect = startRect
|
|
122
|
+
rect = startRect
|
|
123
|
+
} else {
|
|
124
|
+
startRect = lineRect(startLine, startX, layout.getLineRight(startLine))
|
|
125
|
+
endRect = lineRect(endLine, layout.getLineLeft(endLine), endX)
|
|
126
|
+
rect =
|
|
127
|
+
SelectionRect.fromPx(
|
|
128
|
+
originX,
|
|
129
|
+
layout.getLineTop(startLine) + originY,
|
|
130
|
+
layout.width + originX,
|
|
131
|
+
layout.getLineBottom(endLine) + originY,
|
|
132
|
+
)
|
|
133
|
+
}
|
|
134
|
+
|
|
135
|
+
return TextSelection(
|
|
136
|
+
text = selectedText,
|
|
137
|
+
markdown = markdown,
|
|
138
|
+
fullSelection = start == 0 && end >= content.length - 1,
|
|
139
|
+
rect = rect,
|
|
140
|
+
startRect = startRect,
|
|
141
|
+
endRect = endRect,
|
|
142
|
+
)
|
|
143
|
+
}
|
|
144
|
+
|
|
145
|
+
/** Clears this text view's selection, which also ends its selection ActionMode. */
|
|
146
|
+
fun TextView.clearTextSelection() {
|
|
147
|
+
val spannable = text as? Spannable ?: return
|
|
148
|
+
Selection.removeSelection(spannable)
|
|
149
|
+
}
|
|
150
|
+
|
|
151
|
+
/**
|
|
152
|
+
* x of [offset] on [line]. At a line's end offset `getPrimaryHorizontal` reports the start
|
|
153
|
+
* of the next line, so a selection ending there uses the line's right edge.
|
|
154
|
+
*/
|
|
155
|
+
private fun lineEndHorizontal(
|
|
156
|
+
layout: Layout,
|
|
157
|
+
line: Int,
|
|
158
|
+
offset: Int,
|
|
159
|
+
): Float =
|
|
160
|
+
if (offset >= layout.getLineEnd(line) && line < layout.lineCount - 1) {
|
|
161
|
+
layout.getLineRight(line)
|
|
162
|
+
} else {
|
|
163
|
+
layout.getPrimaryHorizontal(offset)
|
|
164
|
+
}
|
|
165
|
+
|
|
166
|
+
/**
|
|
167
|
+
* Coalesces selection changes into at most one `onSelectionChange` per frame. The payload is
|
|
168
|
+
* read when the frame fires, so the latest state always reaches JS; a cleared selection is
|
|
169
|
+
* reported right away and drops any pending update. Identical payloads are sent once, so the
|
|
170
|
+
* `setText` passes of streaming don't repeat `active: false`.
|
|
171
|
+
*/
|
|
172
|
+
class SelectionChangeReporter(
|
|
173
|
+
private val view: View,
|
|
174
|
+
private val snapshot: () -> SelectionSnapshot,
|
|
175
|
+
private val emit: (SelectionSnapshot) -> Unit,
|
|
176
|
+
) {
|
|
177
|
+
var enabled = false
|
|
178
|
+
set(value) {
|
|
179
|
+
if (field == value) return
|
|
180
|
+
field = value
|
|
181
|
+
cancel()
|
|
182
|
+
lastReported = SelectionSnapshot.INACTIVE
|
|
183
|
+
if (value) schedule()
|
|
184
|
+
}
|
|
185
|
+
|
|
186
|
+
private var lastReported = SelectionSnapshot.INACTIVE
|
|
187
|
+
private var pending = false
|
|
188
|
+
private val flushRunnable =
|
|
189
|
+
Runnable {
|
|
190
|
+
pending = false
|
|
191
|
+
report()
|
|
192
|
+
}
|
|
193
|
+
|
|
194
|
+
/** Reports the current state on the next frame. */
|
|
195
|
+
fun schedule() {
|
|
196
|
+
if (!enabled || pending) return
|
|
197
|
+
pending = true
|
|
198
|
+
view.postOnAnimation(flushRunnable)
|
|
199
|
+
}
|
|
200
|
+
|
|
201
|
+
fun onSelectionChanged(hasSelection: Boolean) {
|
|
202
|
+
if (hasSelection) schedule() else flushNow()
|
|
203
|
+
}
|
|
204
|
+
|
|
205
|
+
/** Reports the current state right away, dropping any pending frame. */
|
|
206
|
+
fun flushNow() {
|
|
207
|
+
cancel()
|
|
208
|
+
report()
|
|
209
|
+
}
|
|
210
|
+
|
|
211
|
+
/**
|
|
212
|
+
* Makes the next report go out even if it equals the last one — a block long-pressed
|
|
213
|
+
* again is a new request for the app's menu, not a repeat.
|
|
214
|
+
*/
|
|
215
|
+
fun forgetLastReported() {
|
|
216
|
+
lastReported = SelectionSnapshot.INACTIVE
|
|
217
|
+
}
|
|
218
|
+
|
|
219
|
+
fun cancel() {
|
|
220
|
+
if (!pending) return
|
|
221
|
+
pending = false
|
|
222
|
+
view.removeCallbacks(flushRunnable)
|
|
223
|
+
}
|
|
224
|
+
|
|
225
|
+
private fun report() {
|
|
226
|
+
if (!enabled) return
|
|
227
|
+
val current = snapshot()
|
|
228
|
+
if (current == lastReported) return
|
|
229
|
+
lastReported = current
|
|
230
|
+
emit(current)
|
|
231
|
+
}
|
|
232
|
+
}
|
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
package com.swmansion.enriched.markdown.views
|
|
2
|
+
|
|
3
|
+
import com.swmansion.enriched.markdown.utils.text.view.SelectionMenuConfig
|
|
4
|
+
|
|
5
|
+
/** Receives an intercepted block Copy: the block's Markdown and its raw content. */
|
|
6
|
+
typealias BlockCopyRequest = (markdown: String, text: String) -> Unit
|
|
7
|
+
|
|
8
|
+
/**
|
|
9
|
+
* Selection-menu options that table, math and code block views need for their
|
|
10
|
+
* own long-press menus. Every default keeps the legacy behavior, so a block view
|
|
11
|
+
* that has not received options yet behaves exactly as before.
|
|
12
|
+
*/
|
|
13
|
+
data class BlockMenuOptions(
|
|
14
|
+
val copyHidden: Boolean = false,
|
|
15
|
+
// The Copy item writes the block's Markdown instead of its raw content.
|
|
16
|
+
val copyWritesMarkdown: Boolean = false,
|
|
17
|
+
val copyAsMarkdownHidden: Boolean = false,
|
|
18
|
+
// Hides the copy button in the code block header.
|
|
19
|
+
val copyButtonHidden: Boolean = false,
|
|
20
|
+
// Set when `onCopy` is on: the Copy item hands the content here instead of
|
|
21
|
+
// writing the clipboard. The host binds it to the block's source.
|
|
22
|
+
val onCopyRequest: BlockCopyRequest? = null,
|
|
23
|
+
) {
|
|
24
|
+
val hasItems: Boolean get() = !copyHidden || !copyAsMarkdownHidden
|
|
25
|
+
|
|
26
|
+
companion object {
|
|
27
|
+
fun from(
|
|
28
|
+
config: SelectionMenuConfig,
|
|
29
|
+
onCopyRequest: BlockCopyRequest? = null,
|
|
30
|
+
) = BlockMenuOptions(
|
|
31
|
+
copyHidden = !config.copyEnabled,
|
|
32
|
+
copyWritesMarkdown = config.copyFormatMarkdown,
|
|
33
|
+
copyAsMarkdownHidden = !config.copyAsMarkdown,
|
|
34
|
+
copyButtonHidden = !config.codeBlockCopyButton,
|
|
35
|
+
onCopyRequest = onCopyRequest.takeIf { config.interceptCopy },
|
|
36
|
+
)
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
/** Adds the Copy / Copy as Markdown items shared by the table, math and code block menus. */
|
|
41
|
+
fun ContextMenuPopup.Builder.blockCopyItems(
|
|
42
|
+
options: BlockMenuOptions,
|
|
43
|
+
copyLabel: String,
|
|
44
|
+
copyAsMarkdownLabel: String,
|
|
45
|
+
// The block's Markdown and raw content, read only for an intercepted Copy.
|
|
46
|
+
markdown: () -> String,
|
|
47
|
+
rawText: () -> String,
|
|
48
|
+
copyRaw: () -> Unit,
|
|
49
|
+
copyMarkdown: () -> Unit,
|
|
50
|
+
) {
|
|
51
|
+
if (!options.copyHidden) {
|
|
52
|
+
val onCopyRequest = options.onCopyRequest
|
|
53
|
+
val onCopy =
|
|
54
|
+
when {
|
|
55
|
+
onCopyRequest != null -> { -> onCopyRequest(markdown(), rawText()) }
|
|
56
|
+
options.copyWritesMarkdown -> copyMarkdown
|
|
57
|
+
else -> copyRaw
|
|
58
|
+
}
|
|
59
|
+
item(ContextMenuPopup.Icon.COPY, copyLabel, onCopy)
|
|
60
|
+
}
|
|
61
|
+
if (!options.copyAsMarkdownHidden) {
|
|
62
|
+
item(ContextMenuPopup.Icon.DOCUMENT, copyAsMarkdownLabel, copyMarkdown)
|
|
63
|
+
}
|
|
64
|
+
}
|