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
|
@@ -12,6 +12,12 @@ class CheckboxTouchHelper(
|
|
|
12
12
|
) {
|
|
13
13
|
var onCheckboxTap: ((taskIndex: Int, checked: Boolean, itemText: String) -> Unit)? = null
|
|
14
14
|
|
|
15
|
+
/**
|
|
16
|
+
* When false, checkbox taps are ignored: hit-testing is skipped and no
|
|
17
|
+
* gesture is consumed, so the tap falls through to the text view unchanged.
|
|
18
|
+
*/
|
|
19
|
+
var isEnabled: Boolean = true
|
|
20
|
+
|
|
15
21
|
private var touchDownX = 0f
|
|
16
22
|
private var touchDownY = 0f
|
|
17
23
|
private var pendingHit: TaskListHitTestResult? = null
|
|
@@ -19,6 +25,7 @@ class CheckboxTouchHelper(
|
|
|
19
25
|
|
|
20
26
|
/** Returns `true` if the event was consumed by a checkbox gesture. */
|
|
21
27
|
fun onTouchEvent(event: MotionEvent): Boolean {
|
|
28
|
+
if (!isEnabled) return false
|
|
22
29
|
when (event.actionMasked) {
|
|
23
30
|
MotionEvent.ACTION_DOWN -> {
|
|
24
31
|
val hit = TaskListTapUtils.hitTest(textView, event.x, event.y) ?: return false
|
|
@@ -8,6 +8,8 @@ import android.text.style.StrikethroughSpan
|
|
|
8
8
|
import android.widget.TextView
|
|
9
9
|
import com.swmansion.enriched.markdown.renderer.SpanStyleCache
|
|
10
10
|
import com.swmansion.enriched.markdown.spans.BaseListSpan
|
|
11
|
+
import com.swmansion.enriched.markdown.spans.CodeBlockSpan
|
|
12
|
+
import com.swmansion.enriched.markdown.spans.ListMarkerAnchorSpan
|
|
11
13
|
import com.swmansion.enriched.markdown.spans.TaskListSpan
|
|
12
14
|
import com.swmansion.enriched.markdown.styles.StyleConfig
|
|
13
15
|
import com.swmansion.enriched.markdown.utils.text.span.SPAN_FLAGS_EXCLUSIVE_EXCLUSIVE
|
|
@@ -101,51 +103,69 @@ object TaskListTapUtils {
|
|
|
101
103
|
}
|
|
102
104
|
|
|
103
105
|
val spannable = SpannableStringBuilder(text)
|
|
104
|
-
val
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
106
|
+
val targetSpans =
|
|
107
|
+
spannable
|
|
108
|
+
.getSpans(0, spannable.length, TaskListSpan::class.java)
|
|
109
|
+
.filter { it.taskIndex == targetIndex }
|
|
110
|
+
if (targetSpans.isEmpty()) {
|
|
108
111
|
return false
|
|
109
112
|
}
|
|
110
113
|
|
|
111
|
-
if (
|
|
114
|
+
if (targetSpans.all { it.isChecked == newChecked }) {
|
|
112
115
|
return true
|
|
113
116
|
}
|
|
114
117
|
|
|
115
|
-
val
|
|
116
|
-
val
|
|
117
|
-
val
|
|
118
|
+
val itemDepth = targetSpans.first().depth
|
|
119
|
+
val spanStart = targetSpans.minOf { spannable.getSpanStart(it) }
|
|
120
|
+
val spanEnd = targetSpans.maxOf { spannable.getSpanEnd(it) }
|
|
118
121
|
|
|
119
122
|
val styleCache = SpanStyleCache(styleConfig)
|
|
120
|
-
|
|
123
|
+
|
|
124
|
+
fun toggledCopy(old: TaskListSpan): TaskListSpan =
|
|
121
125
|
TaskListSpan(
|
|
122
126
|
taskStyle = styleConfig.taskListStyle,
|
|
123
127
|
listStyle = styleConfig.listStyle,
|
|
124
|
-
depth =
|
|
128
|
+
depth = old.depth,
|
|
125
129
|
context = textView.context,
|
|
126
130
|
styleCache = styleCache,
|
|
127
131
|
taskIndex = targetIndex,
|
|
128
132
|
isChecked = newChecked,
|
|
133
|
+
drawsMarker = old.drawsMarker,
|
|
129
134
|
)
|
|
130
135
|
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
return false
|
|
136
|
+
// Replace every segment of the item — spans are split around code blocks
|
|
137
|
+
for (old in targetSpans) {
|
|
138
|
+
val start = spannable.getSpanStart(old)
|
|
139
|
+
val end = spannable.getSpanEnd(old)
|
|
140
|
+
spannable.removeSpan(old)
|
|
141
|
+
spannable.setSpan(toggledCopy(old), start, end, SPAN_FLAGS_EXCLUSIVE_EXCLUSIVE)
|
|
138
142
|
}
|
|
139
143
|
|
|
144
|
+
// The marker may be drawn by an anchor span wrapping an unattached copy
|
|
145
|
+
spannable
|
|
146
|
+
.getSpans(0, spannable.length, ListMarkerAnchorSpan::class.java)
|
|
147
|
+
.filter { (it.marker as? TaskListSpan)?.taskIndex == targetIndex }
|
|
148
|
+
.forEach { old ->
|
|
149
|
+
val start = spannable.getSpanStart(old)
|
|
150
|
+
val end = spannable.getSpanEnd(old)
|
|
151
|
+
spannable.removeSpan(old)
|
|
152
|
+
spannable.setSpan(
|
|
153
|
+
ListMarkerAnchorSpan(toggledCopy(old.marker as TaskListSpan)),
|
|
154
|
+
start,
|
|
155
|
+
end,
|
|
156
|
+
SPAN_FLAGS_EXCLUSIVE_EXCLUSIVE,
|
|
157
|
+
)
|
|
158
|
+
}
|
|
159
|
+
|
|
140
160
|
val taskStyle = styleConfig.taskListStyle
|
|
141
161
|
val checkedTextColor = taskStyle.checkedTextColor
|
|
142
162
|
val strikethrough = taskStyle.checkedStrikethrough
|
|
143
163
|
|
|
144
164
|
val excludedRanges =
|
|
145
|
-
|
|
146
|
-
.getSpans(spanStart, spanEnd, BaseListSpan::class.java)
|
|
147
|
-
|
|
148
|
-
|
|
165
|
+
(
|
|
166
|
+
spannable.getSpans(spanStart, spanEnd, BaseListSpan::class.java).filter { it.depth > itemDepth } +
|
|
167
|
+
spannable.getSpans(spanStart, spanEnd, CodeBlockSpan::class.java).toList()
|
|
168
|
+
).map { spannable.getSpanStart(it) to spannable.getSpanEnd(it) }
|
|
149
169
|
.sortedBy { it.first }
|
|
150
170
|
|
|
151
171
|
applyDecorationsToRanges(
|
package/android/src/main/java/com/swmansion/enriched/markdown/utils/text/span/BlockSpacing.kt
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
package com.swmansion.enriched.markdown.utils.text.span
|
|
2
2
|
|
|
3
3
|
import android.text.SpannableStringBuilder
|
|
4
|
+
import com.swmansion.enriched.markdown.spans.CodeBlockSpan
|
|
4
5
|
import com.swmansion.enriched.markdown.spans.ImageSpan
|
|
5
6
|
import com.swmansion.enriched.markdown.spans.LineHeightSpan
|
|
6
7
|
import com.swmansion.enriched.markdown.spans.MarginBottomSpan
|
|
@@ -11,9 +12,9 @@ fun createLineHeightSpan(lineHeight: Float): AndroidLineHeightSpan = LineHeightS
|
|
|
11
12
|
|
|
12
13
|
/**
|
|
13
14
|
* Applies [LineHeightSpan] to [start]..[end] but skips ranges occupied by
|
|
14
|
-
* block [ImageSpan]s (and their trailing '\n')
|
|
15
|
-
*
|
|
16
|
-
*
|
|
15
|
+
* block [ImageSpan]s (and their trailing '\n') and by [CodeBlockSpan]s —
|
|
16
|
+
* both of these apply their own font-metric adjustments that a fixed
|
|
17
|
+
* line height would override.
|
|
17
18
|
*/
|
|
18
19
|
fun applyLineHeightSkippingImages(
|
|
19
20
|
builder: SpannableStringBuilder,
|
|
@@ -26,19 +27,25 @@ fun applyLineHeightSkippingImages(
|
|
|
26
27
|
.getSpans(start, end, ImageSpan::class.java)
|
|
27
28
|
.filter { !it.isInline }
|
|
28
29
|
.map { builder.getSpanStart(it) to builder.getSpanEnd(it) }
|
|
29
|
-
|
|
30
|
+
|
|
31
|
+
val codeBlockRanges =
|
|
32
|
+
builder
|
|
33
|
+
.getSpans(start, end, CodeBlockSpan::class.java)
|
|
34
|
+
.map { builder.getSpanStart(it) to builder.getSpanEnd(it) }
|
|
35
|
+
|
|
36
|
+
val excludedRanges = (blockImageRanges + codeBlockRanges).sortedBy { it.first }
|
|
30
37
|
|
|
31
38
|
var pos = start
|
|
32
|
-
for ((
|
|
33
|
-
if (pos <
|
|
39
|
+
for ((exStart, exEnd) in excludedRanges) {
|
|
40
|
+
if (pos < exStart) {
|
|
34
41
|
builder.setSpan(
|
|
35
42
|
createLineHeightSpan(lineHeight),
|
|
36
43
|
pos,
|
|
37
|
-
|
|
44
|
+
exStart,
|
|
38
45
|
SPAN_FLAGS_EXCLUSIVE_EXCLUSIVE,
|
|
39
46
|
)
|
|
40
47
|
}
|
|
41
|
-
val skipEnd = if (
|
|
48
|
+
val skipEnd = if (exEnd < end && builder[exEnd] == '\n') exEnd + 1 else exEnd
|
|
42
49
|
pos = maxOf(pos, skipEnd)
|
|
43
50
|
}
|
|
44
51
|
if (pos < end) {
|
package/android/src/main/java/com/swmansion/enriched/markdown/utils/text/view/HeadlessActionMode.kt
ADDED
|
@@ -0,0 +1,88 @@
|
|
|
1
|
+
package com.swmansion.enriched.markdown.utils.text.view
|
|
2
|
+
|
|
3
|
+
import android.view.ActionMode
|
|
4
|
+
import android.view.Menu
|
|
5
|
+
import android.view.MenuInflater
|
|
6
|
+
import android.view.View
|
|
7
|
+
import android.widget.PopupMenu
|
|
8
|
+
|
|
9
|
+
/**
|
|
10
|
+
* Stands in for the floating text-selection toolbar while `contextMenuHidden`
|
|
11
|
+
* is on. An empty menu only hides the AOSP FloatingToolbar; ROMs that draw
|
|
12
|
+
* their own selection popup (MIUI) still show it. Answering the Editor's
|
|
13
|
+
* startActionMode with this mode means no toolbar window is ever created.
|
|
14
|
+
*
|
|
15
|
+
* The callback is the Editor's TextActionModeCallback wrapping ours, so it
|
|
16
|
+
* still gets the full create/prepare/destroy lifecycle: Editor keeps the
|
|
17
|
+
* selection handles and its transient-state bookkeeping, and finish() clears
|
|
18
|
+
* the selection exactly as dismissing the real toolbar would.
|
|
19
|
+
*/
|
|
20
|
+
internal class HeadlessActionMode private constructor(
|
|
21
|
+
private val view: View,
|
|
22
|
+
private val callback: ActionMode.Callback,
|
|
23
|
+
) : ActionMode() {
|
|
24
|
+
// A real framework menu: Editor populates it with MenuItem calls
|
|
25
|
+
// (setAlphabeticShortcut, setShowAsAction, setIntent) a stub can't take.
|
|
26
|
+
private val menu: Menu = PopupMenu(view.context, view).menu
|
|
27
|
+
private var finished = false
|
|
28
|
+
|
|
29
|
+
override fun setTitle(title: CharSequence?) = Unit
|
|
30
|
+
|
|
31
|
+
override fun setTitle(resId: Int) = Unit
|
|
32
|
+
|
|
33
|
+
override fun setSubtitle(subtitle: CharSequence?) = Unit
|
|
34
|
+
|
|
35
|
+
override fun setSubtitle(resId: Int) = Unit
|
|
36
|
+
|
|
37
|
+
override fun setCustomView(view: View?) = Unit
|
|
38
|
+
|
|
39
|
+
override fun invalidate() {
|
|
40
|
+
if (!finished) callback.onPrepareActionMode(this, menu)
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
override fun invalidateContentRect() = Unit
|
|
44
|
+
|
|
45
|
+
override fun hide(duration: Long) = Unit
|
|
46
|
+
|
|
47
|
+
override fun finish() {
|
|
48
|
+
if (finished) return
|
|
49
|
+
finished = true
|
|
50
|
+
callback.onDestroyActionMode(this)
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
override fun getMenu(): Menu = menu
|
|
54
|
+
|
|
55
|
+
override fun getTitle(): CharSequence? = null
|
|
56
|
+
|
|
57
|
+
override fun getSubtitle(): CharSequence? = null
|
|
58
|
+
|
|
59
|
+
override fun getCustomView(): View? = null
|
|
60
|
+
|
|
61
|
+
override fun getMenuInflater(): MenuInflater = MenuInflater(view.context)
|
|
62
|
+
|
|
63
|
+
companion object {
|
|
64
|
+
/** Mirrors the framework: null when the callback declines to start. */
|
|
65
|
+
fun start(
|
|
66
|
+
view: View,
|
|
67
|
+
callback: ActionMode.Callback,
|
|
68
|
+
): ActionMode? {
|
|
69
|
+
val mode = HeadlessActionMode(view, callback)
|
|
70
|
+
mode.type = TYPE_FLOATING
|
|
71
|
+
if (!callback.onCreateActionMode(mode, mode.menu)) return null
|
|
72
|
+
callback.onPrepareActionMode(mode, mode.menu)
|
|
73
|
+
return mode
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
/**
|
|
79
|
+
* MIUI 12 (Android 10) replaces android.widget.Editor: text selection never reaches
|
|
80
|
+
* startActionMode or the custom ActionMode callback, so HeadlessActionMode is never used.
|
|
81
|
+
* Its own popup is shown by Editor$HandleView.showActionPopupWindow, which posts a runnable
|
|
82
|
+
* on the TextView (Editor$HandleView$2). Dropping that runnable is the only hook left while
|
|
83
|
+
* `contextMenuHidden` is on.
|
|
84
|
+
*/
|
|
85
|
+
private const val ROM_SELECTION_POPUP_SHOWER_PREFIX = "android.widget.Editor\$HandleView"
|
|
86
|
+
|
|
87
|
+
internal fun isRomSelectionPopupShower(action: Runnable?): Boolean =
|
|
88
|
+
action != null && action.javaClass.name.startsWith(ROM_SELECTION_POPUP_SHOWER_PREFIX)
|
package/android/src/main/java/com/swmansion/enriched/markdown/utils/text/view/LinkLayoutCollector.kt
ADDED
|
@@ -0,0 +1,100 @@
|
|
|
1
|
+
package com.swmansion.enriched.markdown.utils.text.view
|
|
2
|
+
|
|
3
|
+
import android.text.Layout
|
|
4
|
+
import android.text.Spanned
|
|
5
|
+
import android.widget.TextView
|
|
6
|
+
import com.facebook.react.uimanager.PixelUtil
|
|
7
|
+
import com.swmansion.enriched.markdown.spans.LinkChipBackgroundSpan
|
|
8
|
+
import com.swmansion.enriched.markdown.spans.LinkSpacers
|
|
9
|
+
import com.swmansion.enriched.markdown.spans.LinkSpan
|
|
10
|
+
import kotlin.math.max
|
|
11
|
+
import kotlin.math.min
|
|
12
|
+
|
|
13
|
+
/** One laid-out line of a link, in dp relative to the reporting view. Covers the drawn chip. */
|
|
14
|
+
data class LinkLayoutFragment(
|
|
15
|
+
val linkIndex: Int,
|
|
16
|
+
val url: String,
|
|
17
|
+
val text: String,
|
|
18
|
+
val x: Float,
|
|
19
|
+
val y: Float,
|
|
20
|
+
val width: Float,
|
|
21
|
+
val height: Float,
|
|
22
|
+
)
|
|
23
|
+
|
|
24
|
+
object LinkLayoutCollector {
|
|
25
|
+
/**
|
|
26
|
+
* Collects the chip rect of every link fragment laid out in [textView], for `onLinkLayout`.
|
|
27
|
+
* Rects are offset by the text view's own padding plus [offsetXPx]/[offsetYPx] (a segment's
|
|
28
|
+
* position inside its container), then converted to dp. Links are numbered in document order
|
|
29
|
+
* from [indexBase]; returns the fragments and the number of links found.
|
|
30
|
+
*/
|
|
31
|
+
fun collect(
|
|
32
|
+
textView: TextView,
|
|
33
|
+
offsetXPx: Int = 0,
|
|
34
|
+
offsetYPx: Int = 0,
|
|
35
|
+
indexBase: Int = 0,
|
|
36
|
+
): Pair<List<LinkLayoutFragment>, Int> {
|
|
37
|
+
val layout = textView.layout ?: return emptyList<LinkLayoutFragment>() to 0
|
|
38
|
+
val text = textView.text as? Spanned ?: return emptyList<LinkLayoutFragment>() to 0
|
|
39
|
+
|
|
40
|
+
// LinkRenderer sets one LinkChipBackgroundSpan per link, spacers included.
|
|
41
|
+
val chips =
|
|
42
|
+
text
|
|
43
|
+
.getSpans(0, text.length, LinkChipBackgroundSpan::class.java)
|
|
44
|
+
.sortedBy { text.getSpanStart(it) }
|
|
45
|
+
val originX = offsetXPx + textView.totalPaddingLeft
|
|
46
|
+
val originY = offsetYPx + textView.totalPaddingTop
|
|
47
|
+
|
|
48
|
+
val fragments = mutableListOf<LinkLayoutFragment>()
|
|
49
|
+
chips.forEachIndexed { i, chipSpan ->
|
|
50
|
+
val start = text.getSpanStart(chipSpan)
|
|
51
|
+
val end = text.getSpanEnd(chipSpan)
|
|
52
|
+
if (start !in 0 until end) return@forEachIndexed
|
|
53
|
+
|
|
54
|
+
val url = text.getSpans(start, end, LinkSpan::class.java).firstOrNull()?.url ?: ""
|
|
55
|
+
val linkText = LinkSpacers.strip(text.subSequence(start, end)).toString()
|
|
56
|
+
val (ascent, descent) = LinkChipBackgroundSpan.linkFontMetrics(text, start, end, textView.paint)
|
|
57
|
+
val paddingVertical = chipSpan.chip.paddingVertical
|
|
58
|
+
|
|
59
|
+
for (line in layout.getLineForOffset(start)..layout.getLineForOffset(end - 1)) {
|
|
60
|
+
val fragmentStart = max(start, layout.getLineStart(line))
|
|
61
|
+
val fragmentEnd =
|
|
62
|
+
LinkChipBackgroundSpan.trimTrailingWhitespace(text, fragmentStart, min(end, layout.getLineEnd(line)))
|
|
63
|
+
if (fragmentEnd <= fragmentStart) continue
|
|
64
|
+
|
|
65
|
+
val left = layout.getPrimaryHorizontal(fragmentStart)
|
|
66
|
+
val right = lineEndHorizontal(layout, line, fragmentEnd)
|
|
67
|
+
val baseline = layout.getLineBaseline(line).toFloat()
|
|
68
|
+
val top = baseline + ascent - paddingVertical
|
|
69
|
+
val bottom = baseline + descent + paddingVertical
|
|
70
|
+
|
|
71
|
+
fragments +=
|
|
72
|
+
LinkLayoutFragment(
|
|
73
|
+
linkIndex = indexBase + i,
|
|
74
|
+
url = url,
|
|
75
|
+
text = linkText,
|
|
76
|
+
x = PixelUtil.toDIPFromPixel(min(left, right) + originX),
|
|
77
|
+
y = PixelUtil.toDIPFromPixel(top + originY),
|
|
78
|
+
width = PixelUtil.toDIPFromPixel(kotlin.math.abs(right - left)),
|
|
79
|
+
height = PixelUtil.toDIPFromPixel(bottom - top),
|
|
80
|
+
)
|
|
81
|
+
}
|
|
82
|
+
}
|
|
83
|
+
return fragments to chips.size
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
/**
|
|
87
|
+
* x of [offset] on [line]. At a line's end offset `getPrimaryHorizontal` reports the start
|
|
88
|
+
* of the next line (the same offset), so a fragment cut mid-word uses the line's right edge.
|
|
89
|
+
*/
|
|
90
|
+
private fun lineEndHorizontal(
|
|
91
|
+
layout: Layout,
|
|
92
|
+
line: Int,
|
|
93
|
+
offset: Int,
|
|
94
|
+
): Float =
|
|
95
|
+
if (offset >= layout.getLineEnd(line) && line < layout.lineCount - 1) {
|
|
96
|
+
layout.getLineRight(line)
|
|
97
|
+
} else {
|
|
98
|
+
layout.getPrimaryHorizontal(offset)
|
|
99
|
+
}
|
|
100
|
+
}
|
|
@@ -2,9 +2,8 @@ package com.swmansion.enriched.markdown.utils.text.view
|
|
|
2
2
|
|
|
3
3
|
import android.os.Handler
|
|
4
4
|
import android.os.Looper
|
|
5
|
-
import android.text.Selection
|
|
6
5
|
import android.text.Spannable
|
|
7
|
-
import android.text.method.
|
|
6
|
+
import android.text.method.ArrowKeyMovementMethod
|
|
8
7
|
import android.view.MotionEvent
|
|
9
8
|
import android.view.ViewConfiguration
|
|
10
9
|
import android.widget.TextView
|
|
@@ -13,15 +12,26 @@ import com.swmansion.enriched.markdown.spans.SpoilerSpan
|
|
|
13
12
|
import com.swmansion.enriched.markdown.spoiler.SpoilerCapable
|
|
14
13
|
import kotlin.math.abs
|
|
15
14
|
|
|
16
|
-
|
|
15
|
+
/**
|
|
16
|
+
* Movement method that adds link tap / long-press and spoiler tap handling on
|
|
17
|
+
* top of [ArrowKeyMovementMethod], the method [setTextIsSelectable] installs.
|
|
18
|
+
*
|
|
19
|
+
* Must never mutate the buffer's Selection spans — the platform Editor
|
|
20
|
+
* manages them during long-press gestures, and removing or overwriting
|
|
21
|
+
* them mid-gesture crashes on some OEM skins.
|
|
22
|
+
* See: https://github.com/software-mansion/enriched-markdown/issues/580
|
|
23
|
+
*/
|
|
24
|
+
class LinkLongPressMovementMethod : ArrowKeyMovementMethod() {
|
|
17
25
|
private val handler = Handler(Looper.getMainLooper())
|
|
18
26
|
private var longPressRunnable: Runnable? = null
|
|
19
27
|
|
|
20
28
|
private var startX = 0f
|
|
21
29
|
private var startY = 0f
|
|
30
|
+
private var pressedLink: LinkSpan? = null
|
|
22
31
|
|
|
23
32
|
var isLinkTouchActive: Boolean = false
|
|
24
33
|
private set
|
|
34
|
+
private var isTouchWithinTextBounds: Boolean = true
|
|
25
35
|
|
|
26
36
|
override fun onTouchEvent(
|
|
27
37
|
widget: TextView,
|
|
@@ -33,9 +43,10 @@ class LinkLongPressMovementMethod : LinkMovementMethod() {
|
|
|
33
43
|
startX = event.x
|
|
34
44
|
startY = event.y
|
|
35
45
|
|
|
36
|
-
|
|
37
|
-
isLinkTouchActive =
|
|
38
|
-
|
|
46
|
+
pressedLink = findLinkSpan(widget, buffer, event)
|
|
47
|
+
isLinkTouchActive = pressedLink != null
|
|
48
|
+
isTouchWithinTextBounds = charOffsetAt(widget, event) != null
|
|
49
|
+
pressedLink?.let { scheduleLongPress(widget, it) }
|
|
39
50
|
}
|
|
40
51
|
|
|
41
52
|
MotionEvent.ACTION_MOVE -> {
|
|
@@ -45,17 +56,25 @@ class LinkLongPressMovementMethod : LinkMovementMethod() {
|
|
|
45
56
|
) {
|
|
46
57
|
cancelLongPress()
|
|
47
58
|
isLinkTouchActive = false
|
|
59
|
+
pressedLink = null
|
|
48
60
|
}
|
|
49
61
|
}
|
|
50
62
|
|
|
51
63
|
MotionEvent.ACTION_UP -> {
|
|
52
64
|
cancelLongPress()
|
|
65
|
+
val tappedLink = pressedLink
|
|
53
66
|
isLinkTouchActive = false
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
}
|
|
67
|
+
pressedLink = null
|
|
68
|
+
|
|
57
69
|
if (handleSpoilerTap(widget, buffer, event)) {
|
|
58
|
-
|
|
70
|
+
return true
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
// LinkSpan.onClick itself swallows the click that follows a completed
|
|
74
|
+
// long-press (and resets its internal flag), so it is always invoked
|
|
75
|
+
// for a tap that started and ended on the same link.
|
|
76
|
+
if (tappedLink != null && findLinkSpan(widget, buffer, event) === tappedLink) {
|
|
77
|
+
tappedLink.onClick(widget)
|
|
59
78
|
return true
|
|
60
79
|
}
|
|
61
80
|
}
|
|
@@ -63,22 +82,19 @@ class LinkLongPressMovementMethod : LinkMovementMethod() {
|
|
|
63
82
|
MotionEvent.ACTION_CANCEL -> {
|
|
64
83
|
cancelLongPress()
|
|
65
84
|
isLinkTouchActive = false
|
|
66
|
-
|
|
67
|
-
Selection.removeSelection(buffer)
|
|
68
|
-
}
|
|
85
|
+
pressedLink = null
|
|
69
86
|
}
|
|
70
87
|
}
|
|
71
88
|
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
//
|
|
75
|
-
//
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
Selection.removeSelection(buffer)
|
|
89
|
+
// getOffsetForHorizontal snaps to the nearest character, so without this
|
|
90
|
+
// guard taps in empty space past the end of a line would still be treated
|
|
91
|
+
// as text touches. Let them fall through to the parent (e.g. RNGH
|
|
92
|
+
// Pressable) instead.
|
|
93
|
+
if (!isTouchWithinTextBounds) {
|
|
94
|
+
return false
|
|
79
95
|
}
|
|
80
96
|
|
|
81
|
-
return
|
|
97
|
+
return super.onTouchEvent(widget, buffer, event)
|
|
82
98
|
}
|
|
83
99
|
|
|
84
100
|
private fun scheduleLongPress(
|
|
@@ -89,9 +105,6 @@ class LinkLongPressMovementMethod : LinkMovementMethod() {
|
|
|
89
105
|
|
|
90
106
|
longPressRunnable =
|
|
91
107
|
Runnable {
|
|
92
|
-
if (widget.hasSelection()) {
|
|
93
|
-
Selection.removeSelection(widget.text as Spannable)
|
|
94
|
-
}
|
|
95
108
|
// Execute the long click logic on the span
|
|
96
109
|
if (span.onLongClick(widget)) {
|
|
97
110
|
// If consumed, cancel the system's own long-press logic (like context menus)
|
|
@@ -112,10 +125,28 @@ class LinkLongPressMovementMethod : LinkMovementMethod() {
|
|
|
112
125
|
widget: TextView,
|
|
113
126
|
event: MotionEvent,
|
|
114
127
|
): Int? {
|
|
115
|
-
val x = event.x
|
|
116
|
-
val y = event.y
|
|
128
|
+
val x = event.x - widget.totalPaddingLeft + widget.scrollX
|
|
129
|
+
val y = event.y - widget.totalPaddingTop + widget.scrollY
|
|
117
130
|
val layout = widget.layout ?: return null
|
|
118
|
-
|
|
131
|
+
|
|
132
|
+
// getLineForVertical clamps to the first/last line for out-of-range
|
|
133
|
+
// values, so taps in vertical padding would silently map to a real
|
|
134
|
+
// line. Reject them before proceeding.
|
|
135
|
+
if (y < 0f || y > layout.height) {
|
|
136
|
+
return null
|
|
137
|
+
}
|
|
138
|
+
|
|
139
|
+
val line = layout.getLineForVertical(y.toInt())
|
|
140
|
+
|
|
141
|
+
// getOffsetForHorizontal snaps to the nearest character even when the
|
|
142
|
+
// tap is outside the actual text content (e.g. empty space after the
|
|
143
|
+
// last word on a line). Guard against that by checking the tap falls
|
|
144
|
+
// within the line's text bounds.
|
|
145
|
+
if (x < layout.getLineLeft(line) || x > layout.getLineRight(line)) {
|
|
146
|
+
return null
|
|
147
|
+
}
|
|
148
|
+
|
|
149
|
+
return layout.getOffsetForHorizontal(line, x)
|
|
119
150
|
}
|
|
120
151
|
|
|
121
152
|
private fun findLinkSpan(
|